SlideShare a Scribd company logo
1 of 27
Download to read offline
Automating Source Code Evolutions using
Coccinelle
Julia Lawall (Inria/LIP6)
Joint work with
Gilles Muller, René Rydhof Hansen,
Nicolas Palix
September 24, 2013
1
Legacy software:
Changing priorities, changing requirements
Linux kernel examples:
Booleans:
– Use 0 / 1?
– Use true / false?
Managed memory:
– kmalloc requires kfree, request_irq requires
free_irq
– Devm interface implicitly cleans up allocated resources.
Issues:
These changes require pervasive, scattered modifications.
Nothing forces the changes to be made.
Developers don’t pick up on new coding strategies.
2
The use of booleans over time
Linux
2.6.20
Linux
2.6.22
Linux
2.6.24
Linux
2.6.26
Linux
2.6.28
Linux
2.6.30
Linux
2.6.32
Linux
2.6.34
Linux
2.6.36
Linux
3.0
Linux
3.2
Linux
3.4
Linux
3.6
Linux
3.8
Linux
3.10
0
10000
20000
30000
Occurrences
boolean values
boolean variables
ints in bools
(Roughly every 6 months, February 2007 - June 2013).
3
The use of booleans over time - rate of bad code
Linux
2.6.20
Linux
2.6.22
Linux
2.6.24
Linux
2.6.26
Linux
2.6.28
Linux
2.6.30
Linux
2.6.32
Linux
2.6.34
Linux
2.6.36
Linux
3.0
Linux
3.2
Linux
3.4
Linux
3.6
Linux
3.8
Linux
3.10
0
5
10
15
20
%
int values in bool variables
4
Booleans: A concrete example
Desired property: bool variables should be true or false.
Code fragment:
static bool overlapping_resync_write(struct drbd_conf *mdev, ...) {
struct drbd_peer_request *rs_req;
bool rv = 0;
spin_lock_irq(&mdev->tconn->req_lock);
list_for_each_entry(rs_req, &mdev->sync_ee, w.list) {
if (overlaps(peer_req->i.sector, peer_req->i.size,
rs_req->i.sector, rs_req->i.size)) {
rv = 1;
break;
}
}
spin_unlock_irq(&mdev->tconn->req_lock);
return rv;
}
5
The use of devm functions over time
Linux
2.6.20
Linux
2.6.22
Linux
2.6.24
Linux
2.6.26
Linux
2.6.28
Linux
2.6.30
Linux
2.6.32
Linux
2.6.34
Linux
2.6.36
Linux
3.0
Linux
3.2
Linux
3.4
Linux
3.6
Linux
3.8
Linux
3.10
0
200
400
600
Occurrences
platform kzalloc
platform devm_kzalloc
i2c kzalloc
i2c devm_kzalloc
6
Devm functions: A concrete example
Desired property (simpler than introducing devm functions):
A common pattern is platform_get_resource followed
by devm_ioremap_resource.
devm_ioremap_resource does error handling for
the platform_get_resource value.
Separate error handling is not needed.
Code fragment:
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
ahb->regs = devm_ioremap_resource(&pdev->dev, res);
How to make these changes automatically and
reliably?
Requirements:
Find relevant code.
– grep does this...
Make changes.
– sed does this...
Problem: Grep and sed don’t know about code structure or
semantics.
8
Our approach: Coccinelle
Static analysis to find patterns in C code.
Automatic transformation.
User scriptable, based on patch notation
(semantic patches).
http://coccinelle.lip6.fr/
http://coccinellery.org/
9
Boolean example, part 1
@@ -1932,14 +1932,14 @@
static bool overlapping_resync_write(struct drbd_conf *mdev, ...) {
struct drbd_peer_request *rs_req;
- bool rv = 0;
+ bool rv = false;
spin_lock_irq(&mdev->tconn->req_lock);
list_for_each_entry(rs_req, &mdev->sync_ee, w.list) {
if (overlaps(peer_req->i.sector, peer_req->i.size,
rs_req->i.sector, rs_req->i.size)) {
- rv = 1;
+ rv = true;
break;
}
}
spin_unlock_irq(&mdev->tconn->req_lock);
return rv;
}
First step:
Replace bool b = 0; by bool b = false;
Replace bool b = 1; by bool b = true;
10
Semantic patch: booleans, part 1
@@
identifier b;
@@
bool b =
- 0
+ false
;
@@
identifier b;
@@
bool b =
- 1
+ true
;
Semantic patch application: booleans, part 1
Result:
@@ -1932,14 +1932,14 @@
static bool overlapping_resync_write(struct drbd_conf *mdev, ...) {
struct drbd_peer_request *rs_req;
- bool rv = 0;
+ bool rv = false;
spin_lock_irq(&mdev->tconn->req_lock);
list_for_each_entry(rs_req, &mdev->sync_ee, w.list) {
if (overlaps(peer_req->i.sector, peer_req->i.size,
rs_req->i.sector, rs_req->i.size)) {
rv = 1;
break;
}
}
spin_unlock_irq(&mdev->tconn->req_lock);
return rv;
}
Affects 187 lines, 124 files in Linux 3.10.
Fixes the declaration, but not the subsequent assignment...
Boolean example: part 2
Problem:
We cannot replace every 0 by false, and 1 by true.
The assignment must involve a boolean variable.
Solution: Type constraints on metavariables.
@@ bool b; @@
b =
- 0
+ false
@@ bool b; @@
b =
- 1
+ true
13
Semantic patch application: booleans, part 2
Result:
@@ -1932,14 +1932,14 @@
static bool overlapping_resync_write(struct drbd_conf *mdev, ...) {
struct drbd_peer_request *rs_req;
- bool rv = 0;
+ bool rv = false;
spin_lock_irq(&mdev->tconn->req_lock);
list_for_each_entry(rs_req, &mdev->sync_ee, w.list) {
if (overlaps(peer_req->i.sector, peer_req->i.size,
rs_req->i.sector, rs_req->i.size)) {
- rv = 1;
+ rv = true;
break;
}
}
spin_unlock_irq(&mdev->tconn->req_lock);
return rv;
}
Affects 657 lines, 236 files in Linux 3.10.
14
Remaining issues
Function arguments.
Function return values.
Booleans used with non-bool variables.
Beyond the scope of this talk...
15
platform_get_resource example, part 1
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?");
return -ENODEV;
}
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "no irq resource?");
return -ENODEV;
}
... // 35 lines of code
dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dev->base)) {
r = PTR_ERR(dev->base);
goto err_unuse_clocks;
}
16
platform_get_resource example, part 1
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "no mem resource?");
- return -ENODEV;
- }
...
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dev->base)) {
r = PTR_ERR(dev->base);
goto err_unuse_clocks;
}
Problem: Need both platform_get_resource and
devm_ioremap_resource.
Separated by arbitrary code fragments.
17
Semantic patch: platform_get_resource, part 1
Copy the code fragment, from the first line to the last line
@@
expression res, pdev, n, e, x;
@@
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?");
return -ENODEV;
}
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "no irq resource?");
return -ENODEV;
}
...
dev->base = devm_ioremap_resource(&pdev->dev, mem);
18
Semantic patch: platform_get_resource, part 1
Drop the irrelevant parts
@@
expression res, pdev, n, e, x;
@@
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?");
return -ENODEV;
}
...
dev->base = devm_ioremap_resource(&pdev->dev, mem);
19
Semantic patch: platform_get_resource, part 1
Abstract over irrelevant detailsy
@@
expression mem, pdev, n, e;
statement S;
@@
mem = platform_get_resource(pdev, IORESOURCE_MEM, n);
if (!mem) S
...
e = devm_ioremap_resource(&pdev->dev, mem);
20
Semantic patch: platform_get_resource, part 1
Introduce transformationsy
@@
expression mem, pdev, n, e;
statement S;
@@
- mem = platform_get_resource(pdev, IORESOURCE_MEM, n);
- if (!mem) S
...
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, n);
e = devm_ioremap_resource(&pdev->dev, mem);
21
Semantic patch: platform_get_resource, part 1
Add sanity checks
@@
expression mem, pdev, n, e;
statement S;
@@
- mem = platform_get_resource(pdev, IORESOURCE_MEM, n);
- if (!mem) S
... when != mem
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, n);
e = devm_ioremap_resource(&pdev->dev, mem);
22
Semantic patch application:
platform_get_resource, part 1
Result:
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "no mem resource?");
- return -ENODEV;
- }
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq) {
dev_err(&pdev->dev, "no irq resource?");
return -ENODEV;
}
...
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dev->base)) {
r = PTR_ERR(dev->base);
goto err_unuse_clocks;
}
Affects 42 files in Linux 3.10.
23
platform_get_resource example, part 2
Problem: Some calls are missed because &pdev->dev is
renamed.
Code fragment:
struct device *dev = &pdev->dev;
void __iomem *addr = NULL;
struct stmmac_priv *priv = NULL;
struct plat_stmmacenet_data *plat_dat = NULL;
const char *mac = NULL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
addr = devm_ioremap_resource(dev, res);
if (IS_ERR(addr))
return PTR_ERR(addr);
24
Semantic patch: platform_get_resource, part 2
@@
expression res, pdev, n, e, x, e1, e2;
statement S;
@@
x = &pdev->dev
... when != x = e1
- res = platform_get_resource(pdev, IORESOURCE_MEM, n);
- if (!res) S
... when != mem
when != x = e2
+ res = platform_get_resource(pdev, IORESOURCE_MEM, n);
e = devm_ioremap_resource(x,res);
Result: Updates 4 more files in Linux-3.10.
25
Summary
We have seen the need for:
Search and replace for atomic code fragments.
– Declaration and initialization of boolean variables.
Search and replace using type information.
– Assignments of boolean variables.
Search and replace for scattered code fragments
– platform_get_resource somewhere followed by
devm_iomap_resource.
Taking renamings into account.
– &pdev->dev vs dev.
26
Conclusion
Coccinelle
Define and perform arbitrary transformations across a
code base.
Reasonable performance in most cases.
Boolean example takes 7 minutes on a 4 core laptop.
Impact:
Over 1000 patches in Linux based on Coccinelle.
Over 40 semantic patches in linux/scripts/coccinelle.
http://coccinelle.lip6.fr/
http://coccinellery.org/

More Related Content

What's hot

GPU Programming on CPU - Using C++AMP
GPU Programming on CPU - Using C++AMPGPU Programming on CPU - Using C++AMP
GPU Programming on CPU - Using C++AMP
Miller Lee
 

What's hot (20)

Java Performance: Speedup your application with hardware counters
Java Performance: Speedup your application with hardware countersJava Performance: Speedup your application with hardware counters
Java Performance: Speedup your application with hardware counters
 
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDKEric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
 
Eric Lafortune - The Jack and Jill build system
Eric Lafortune - The Jack and Jill build systemEric Lafortune - The Jack and Jill build system
Eric Lafortune - The Jack and Jill build system
 
JVM Mechanics
JVM MechanicsJVM Mechanics
JVM Mechanics
 
C&cpu
C&cpuC&cpu
C&cpu
 
Functional Reactive Programming on Android
Functional Reactive Programming on AndroidFunctional Reactive Programming on Android
Functional Reactive Programming on Android
 
Joel Falcou, Boost.SIMD
Joel Falcou, Boost.SIMDJoel Falcou, Boost.SIMD
Joel Falcou, Boost.SIMD
 
Zone IDA Proc
Zone IDA ProcZone IDA Proc
Zone IDA Proc
 
GPU Programming on CPU - Using C++AMP
GPU Programming on CPU - Using C++AMPGPU Programming on CPU - Using C++AMP
GPU Programming on CPU - Using C++AMP
 
HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3HKG15-207: Advanced Toolchain Usage Part 3
HKG15-207: Advanced Toolchain Usage Part 3
 
Bridge TensorFlow to run on Intel nGraph backends (v0.4)
Bridge TensorFlow to run on Intel nGraph backends (v0.4)Bridge TensorFlow to run on Intel nGraph backends (v0.4)
Bridge TensorFlow to run on Intel nGraph backends (v0.4)
 
TensorFlow XLA RPC
TensorFlow XLA RPCTensorFlow XLA RPC
TensorFlow XLA RPC
 
Concurrency Concepts in Java
Concurrency Concepts in JavaConcurrency Concepts in Java
Concurrency Concepts in Java
 
Triton and Symbolic execution on GDB@DEF CON China
Triton and Symbolic execution on GDB@DEF CON ChinaTriton and Symbolic execution on GDB@DEF CON China
Triton and Symbolic execution on GDB@DEF CON China
 
C++ amp on linux
C++ amp on linuxC++ amp on linux
C++ amp on linux
 
Feldo: Function Event Listing and Dynamic Observing for Detecting and Prevent...
Feldo: Function Event Listing and Dynamic Observing for Detecting and Prevent...Feldo: Function Event Listing and Dynamic Observing for Detecting and Prevent...
Feldo: Function Event Listing and Dynamic Observing for Detecting and Prevent...
 
TVM VTA (TSIM)
TVM VTA (TSIM) TVM VTA (TSIM)
TVM VTA (TSIM)
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done right
 
Bridge TensorFlow to run on Intel nGraph backends (v0.5)
Bridge TensorFlow to run on Intel nGraph backends (v0.5)Bridge TensorFlow to run on Intel nGraph backends (v0.5)
Bridge TensorFlow to run on Intel nGraph backends (v0.5)
 
Androsia: A step ahead in securing in-memory Android application data by Sami...
Androsia: A step ahead in securing in-memory Android application data by Sami...Androsia: A step ahead in securing in-memory Android application data by Sami...
Androsia: A step ahead in securing in-memory Android application data by Sami...
 

Similar to Kernel Recipes 2013 - Automating source code evolutions using Coccinelle

Node js introduction
Node js introductionNode js introduction
Node js introduction
Alex Su
 

Similar to Kernel Recipes 2013 - Automating source code evolutions using Coccinelle (20)

Easing the Complex with SPBench framework
Easing the Complex with SPBench frameworkEasing the Complex with SPBench framework
Easing the Complex with SPBench framework
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Quality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormQuality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStorm
 
SOLID Ruby SOLID Rails
SOLID Ruby SOLID RailsSOLID Ruby SOLID Rails
SOLID Ruby SOLID Rails
 
Node js introduction
Node js introductionNode js introduction
Node js introduction
 
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' RequestChecking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
Checking the Code of LDAP-Server ReOpenLDAP on Our Readers' Request
 
Extend Redis with Modules
Extend Redis with ModulesExtend Redis with Modules
Extend Redis with Modules
 
Titanium appcelerator best practices
Titanium appcelerator best practicesTitanium appcelerator best practices
Titanium appcelerator best practices
 
20141011 mastering mysqlnd
20141011 mastering mysqlnd20141011 mastering mysqlnd
20141011 mastering mysqlnd
 
Developing a Redis Module - Hackathon Kickoff
 Developing a Redis Module - Hackathon Kickoff Developing a Redis Module - Hackathon Kickoff
Developing a Redis Module - Hackathon Kickoff
 
Real World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS ApplicationReal World Lessons on the Pain Points of Node.JS Application
Real World Lessons on the Pain Points of Node.JS Application
 
How to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita GalkinHow to make a high-quality Node.js app, Nikita Galkin
How to make a high-quality Node.js app, Nikita Galkin
 
Real World Lessons on the Pain Points of Node.js Applications
Real World Lessons on the Pain Points of Node.js ApplicationsReal World Lessons on the Pain Points of Node.js Applications
Real World Lessons on the Pain Points of Node.js Applications
 
NodeJS for Beginner
NodeJS for BeginnerNodeJS for Beginner
NodeJS for Beginner
 
Linux kernel tracing superpowers in the cloud
Linux kernel tracing superpowers in the cloudLinux kernel tracing superpowers in the cloud
Linux kernel tracing superpowers in the cloud
 
2009-02 Oops!
2009-02 Oops!2009-02 Oops!
2009-02 Oops!
 
Fatc
FatcFatc
Fatc
 
"Развитие ветки PHP-7"
"Развитие ветки PHP-7""Развитие ветки PHP-7"
"Развитие ветки PHP-7"
 
Code metrics in PHP
Code metrics in PHPCode metrics in PHP
Code metrics in PHP
 

More from Anne Nicolas

Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary dataKernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Anne Nicolas
 

More from Anne Nicolas (20)

Kernel Recipes 2019 - Driving the industry toward upstream first
Kernel Recipes 2019 - Driving the industry toward upstream firstKernel Recipes 2019 - Driving the industry toward upstream first
Kernel Recipes 2019 - Driving the industry toward upstream first
 
Kernel Recipes 2019 - No NMI? No Problem! – Implementing Arm64 Pseudo-NMI
Kernel Recipes 2019 - No NMI? No Problem! – Implementing Arm64 Pseudo-NMIKernel Recipes 2019 - No NMI? No Problem! – Implementing Arm64 Pseudo-NMI
Kernel Recipes 2019 - No NMI? No Problem! – Implementing Arm64 Pseudo-NMI
 
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernelKernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
 
Kernel Recipes 2019 - Metrics are money
Kernel Recipes 2019 - Metrics are moneyKernel Recipes 2019 - Metrics are money
Kernel Recipes 2019 - Metrics are money
 
Kernel Recipes 2019 - Kernel documentation: past, present, and future
Kernel Recipes 2019 - Kernel documentation: past, present, and futureKernel Recipes 2019 - Kernel documentation: past, present, and future
Kernel Recipes 2019 - Kernel documentation: past, present, and future
 
Embedded Recipes 2019 - Knowing your ARM from your ARSE: wading through the t...
Embedded Recipes 2019 - Knowing your ARM from your ARSE: wading through the t...Embedded Recipes 2019 - Knowing your ARM from your ARSE: wading through the t...
Embedded Recipes 2019 - Knowing your ARM from your ARSE: wading through the t...
 
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary dataKernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
 
Kernel Recipes 2019 - Analyzing changes to the binary interface exposed by th...
Kernel Recipes 2019 - Analyzing changes to the binary interface exposed by th...Kernel Recipes 2019 - Analyzing changes to the binary interface exposed by th...
Kernel Recipes 2019 - Analyzing changes to the binary interface exposed by th...
 
Embedded Recipes 2019 - Remote update adventures with RAUC, Yocto and Barebox
Embedded Recipes 2019 - Remote update adventures with RAUC, Yocto and BareboxEmbedded Recipes 2019 - Remote update adventures with RAUC, Yocto and Barebox
Embedded Recipes 2019 - Remote update adventures with RAUC, Yocto and Barebox
 
Embedded Recipes 2019 - Making embedded graphics less special
Embedded Recipes 2019 - Making embedded graphics less specialEmbedded Recipes 2019 - Making embedded graphics less special
Embedded Recipes 2019 - Making embedded graphics less special
 
Embedded Recipes 2019 - Linux on Open Source Hardware and Libre Silicon
Embedded Recipes 2019 - Linux on Open Source Hardware and Libre SiliconEmbedded Recipes 2019 - Linux on Open Source Hardware and Libre Silicon
Embedded Recipes 2019 - Linux on Open Source Hardware and Libre Silicon
 
Embedded Recipes 2019 - From maintaining I2C to the big (embedded) picture
Embedded Recipes 2019 - From maintaining I2C to the big (embedded) pictureEmbedded Recipes 2019 - From maintaining I2C to the big (embedded) picture
Embedded Recipes 2019 - From maintaining I2C to the big (embedded) picture
 
Embedded Recipes 2019 - Testing firmware the devops way
Embedded Recipes 2019 - Testing firmware the devops wayEmbedded Recipes 2019 - Testing firmware the devops way
Embedded Recipes 2019 - Testing firmware the devops way
 
Embedded Recipes 2019 - Herd your socs become a matchmaker
Embedded Recipes 2019 - Herd your socs become a matchmakerEmbedded Recipes 2019 - Herd your socs become a matchmaker
Embedded Recipes 2019 - Herd your socs become a matchmaker
 
Embedded Recipes 2019 - LLVM / Clang integration
Embedded Recipes 2019 - LLVM / Clang integrationEmbedded Recipes 2019 - LLVM / Clang integration
Embedded Recipes 2019 - LLVM / Clang integration
 
Embedded Recipes 2019 - Introduction to JTAG debugging
Embedded Recipes 2019 - Introduction to JTAG debuggingEmbedded Recipes 2019 - Introduction to JTAG debugging
Embedded Recipes 2019 - Introduction to JTAG debugging
 
Embedded Recipes 2019 - Pipewire a new foundation for embedded multimedia
Embedded Recipes 2019 - Pipewire a new foundation for embedded multimediaEmbedded Recipes 2019 - Pipewire a new foundation for embedded multimedia
Embedded Recipes 2019 - Pipewire a new foundation for embedded multimedia
 
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all started
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all startedKernel Recipes 2019 - ftrace: Where modifying a running kernel all started
Kernel Recipes 2019 - ftrace: Where modifying a running kernel all started
 
Kernel Recipes 2019 - Suricata and XDP
Kernel Recipes 2019 - Suricata and XDPKernel Recipes 2019 - Suricata and XDP
Kernel Recipes 2019 - Suricata and XDP
 
Kernel Recipes 2019 - Marvels of Memory Auto-configuration (SPD)
Kernel Recipes 2019 - Marvels of Memory Auto-configuration (SPD)Kernel Recipes 2019 - Marvels of Memory Auto-configuration (SPD)
Kernel Recipes 2019 - Marvels of Memory Auto-configuration (SPD)
 

Recently uploaded

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 

Kernel Recipes 2013 - Automating source code evolutions using Coccinelle

  • 1. Automating Source Code Evolutions using Coccinelle Julia Lawall (Inria/LIP6) Joint work with Gilles Muller, René Rydhof Hansen, Nicolas Palix September 24, 2013 1
  • 2. Legacy software: Changing priorities, changing requirements Linux kernel examples: Booleans: – Use 0 / 1? – Use true / false? Managed memory: – kmalloc requires kfree, request_irq requires free_irq – Devm interface implicitly cleans up allocated resources. Issues: These changes require pervasive, scattered modifications. Nothing forces the changes to be made. Developers don’t pick up on new coding strategies. 2
  • 3. The use of booleans over time Linux 2.6.20 Linux 2.6.22 Linux 2.6.24 Linux 2.6.26 Linux 2.6.28 Linux 2.6.30 Linux 2.6.32 Linux 2.6.34 Linux 2.6.36 Linux 3.0 Linux 3.2 Linux 3.4 Linux 3.6 Linux 3.8 Linux 3.10 0 10000 20000 30000 Occurrences boolean values boolean variables ints in bools (Roughly every 6 months, February 2007 - June 2013). 3
  • 4. The use of booleans over time - rate of bad code Linux 2.6.20 Linux 2.6.22 Linux 2.6.24 Linux 2.6.26 Linux 2.6.28 Linux 2.6.30 Linux 2.6.32 Linux 2.6.34 Linux 2.6.36 Linux 3.0 Linux 3.2 Linux 3.4 Linux 3.6 Linux 3.8 Linux 3.10 0 5 10 15 20 % int values in bool variables 4
  • 5. Booleans: A concrete example Desired property: bool variables should be true or false. Code fragment: static bool overlapping_resync_write(struct drbd_conf *mdev, ...) { struct drbd_peer_request *rs_req; bool rv = 0; spin_lock_irq(&mdev->tconn->req_lock); list_for_each_entry(rs_req, &mdev->sync_ee, w.list) { if (overlaps(peer_req->i.sector, peer_req->i.size, rs_req->i.sector, rs_req->i.size)) { rv = 1; break; } } spin_unlock_irq(&mdev->tconn->req_lock); return rv; } 5
  • 6. The use of devm functions over time Linux 2.6.20 Linux 2.6.22 Linux 2.6.24 Linux 2.6.26 Linux 2.6.28 Linux 2.6.30 Linux 2.6.32 Linux 2.6.34 Linux 2.6.36 Linux 3.0 Linux 3.2 Linux 3.4 Linux 3.6 Linux 3.8 Linux 3.10 0 200 400 600 Occurrences platform kzalloc platform devm_kzalloc i2c kzalloc i2c devm_kzalloc 6
  • 7. Devm functions: A concrete example Desired property (simpler than introducing devm functions): A common pattern is platform_get_resource followed by devm_ioremap_resource. devm_ioremap_resource does error handling for the platform_get_resource value. Separate error handling is not needed. Code fragment: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; ahb->regs = devm_ioremap_resource(&pdev->dev, res);
  • 8. How to make these changes automatically and reliably? Requirements: Find relevant code. – grep does this... Make changes. – sed does this... Problem: Grep and sed don’t know about code structure or semantics. 8
  • 9. Our approach: Coccinelle Static analysis to find patterns in C code. Automatic transformation. User scriptable, based on patch notation (semantic patches). http://coccinelle.lip6.fr/ http://coccinellery.org/ 9
  • 10. Boolean example, part 1 @@ -1932,14 +1932,14 @@ static bool overlapping_resync_write(struct drbd_conf *mdev, ...) { struct drbd_peer_request *rs_req; - bool rv = 0; + bool rv = false; spin_lock_irq(&mdev->tconn->req_lock); list_for_each_entry(rs_req, &mdev->sync_ee, w.list) { if (overlaps(peer_req->i.sector, peer_req->i.size, rs_req->i.sector, rs_req->i.size)) { - rv = 1; + rv = true; break; } } spin_unlock_irq(&mdev->tconn->req_lock); return rv; } First step: Replace bool b = 0; by bool b = false; Replace bool b = 1; by bool b = true; 10
  • 11. Semantic patch: booleans, part 1 @@ identifier b; @@ bool b = - 0 + false ; @@ identifier b; @@ bool b = - 1 + true ;
  • 12. Semantic patch application: booleans, part 1 Result: @@ -1932,14 +1932,14 @@ static bool overlapping_resync_write(struct drbd_conf *mdev, ...) { struct drbd_peer_request *rs_req; - bool rv = 0; + bool rv = false; spin_lock_irq(&mdev->tconn->req_lock); list_for_each_entry(rs_req, &mdev->sync_ee, w.list) { if (overlaps(peer_req->i.sector, peer_req->i.size, rs_req->i.sector, rs_req->i.size)) { rv = 1; break; } } spin_unlock_irq(&mdev->tconn->req_lock); return rv; } Affects 187 lines, 124 files in Linux 3.10. Fixes the declaration, but not the subsequent assignment...
  • 13. Boolean example: part 2 Problem: We cannot replace every 0 by false, and 1 by true. The assignment must involve a boolean variable. Solution: Type constraints on metavariables. @@ bool b; @@ b = - 0 + false @@ bool b; @@ b = - 1 + true 13
  • 14. Semantic patch application: booleans, part 2 Result: @@ -1932,14 +1932,14 @@ static bool overlapping_resync_write(struct drbd_conf *mdev, ...) { struct drbd_peer_request *rs_req; - bool rv = 0; + bool rv = false; spin_lock_irq(&mdev->tconn->req_lock); list_for_each_entry(rs_req, &mdev->sync_ee, w.list) { if (overlaps(peer_req->i.sector, peer_req->i.size, rs_req->i.sector, rs_req->i.size)) { - rv = 1; + rv = true; break; } } spin_unlock_irq(&mdev->tconn->req_lock); return rv; } Affects 657 lines, 236 files in Linux 3.10. 14
  • 15. Remaining issues Function arguments. Function return values. Booleans used with non-bool variables. Beyond the scope of this talk... 15
  • 16. platform_get_resource example, part 1 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "no mem resource?"); return -ENODEV; } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq) { dev_err(&pdev->dev, "no irq resource?"); return -ENODEV; } ... // 35 lines of code dev->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(dev->base)) { r = PTR_ERR(dev->base); goto err_unuse_clocks; } 16
  • 17. platform_get_resource example, part 1 - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?"); - return -ENODEV; - } ... + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(dev->base)) { r = PTR_ERR(dev->base); goto err_unuse_clocks; } Problem: Need both platform_get_resource and devm_ioremap_resource. Separated by arbitrary code fragments. 17
  • 18. Semantic patch: platform_get_resource, part 1 Copy the code fragment, from the first line to the last line @@ expression res, pdev, n, e, x; @@ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "no mem resource?"); return -ENODEV; } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq) { dev_err(&pdev->dev, "no irq resource?"); return -ENODEV; } ... dev->base = devm_ioremap_resource(&pdev->dev, mem); 18
  • 19. Semantic patch: platform_get_resource, part 1 Drop the irrelevant parts @@ expression res, pdev, n, e, x; @@ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "no mem resource?"); return -ENODEV; } ... dev->base = devm_ioremap_resource(&pdev->dev, mem); 19
  • 20. Semantic patch: platform_get_resource, part 1 Abstract over irrelevant detailsy @@ expression mem, pdev, n, e; statement S; @@ mem = platform_get_resource(pdev, IORESOURCE_MEM, n); if (!mem) S ... e = devm_ioremap_resource(&pdev->dev, mem); 20
  • 21. Semantic patch: platform_get_resource, part 1 Introduce transformationsy @@ expression mem, pdev, n, e; statement S; @@ - mem = platform_get_resource(pdev, IORESOURCE_MEM, n); - if (!mem) S ... + mem = platform_get_resource(pdev, IORESOURCE_MEM, n); e = devm_ioremap_resource(&pdev->dev, mem); 21
  • 22. Semantic patch: platform_get_resource, part 1 Add sanity checks @@ expression mem, pdev, n, e; statement S; @@ - mem = platform_get_resource(pdev, IORESOURCE_MEM, n); - if (!mem) S ... when != mem + mem = platform_get_resource(pdev, IORESOURCE_MEM, n); e = devm_ioremap_resource(&pdev->dev, mem); 22
  • 23. Semantic patch application: platform_get_resource, part 1 Result: - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?"); - return -ENODEV; - } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq) { dev_err(&pdev->dev, "no irq resource?"); return -ENODEV; } ... + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(dev->base)) { r = PTR_ERR(dev->base); goto err_unuse_clocks; } Affects 42 files in Linux 3.10. 23
  • 24. platform_get_resource example, part 2 Problem: Some calls are missed because &pdev->dev is renamed. Code fragment: struct device *dev = &pdev->dev; void __iomem *addr = NULL; struct stmmac_priv *priv = NULL; struct plat_stmmacenet_data *plat_dat = NULL; const char *mac = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; addr = devm_ioremap_resource(dev, res); if (IS_ERR(addr)) return PTR_ERR(addr); 24
  • 25. Semantic patch: platform_get_resource, part 2 @@ expression res, pdev, n, e, x, e1, e2; statement S; @@ x = &pdev->dev ... when != x = e1 - res = platform_get_resource(pdev, IORESOURCE_MEM, n); - if (!res) S ... when != mem when != x = e2 + res = platform_get_resource(pdev, IORESOURCE_MEM, n); e = devm_ioremap_resource(x,res); Result: Updates 4 more files in Linux-3.10. 25
  • 26. Summary We have seen the need for: Search and replace for atomic code fragments. – Declaration and initialization of boolean variables. Search and replace using type information. – Assignments of boolean variables. Search and replace for scattered code fragments – platform_get_resource somewhere followed by devm_iomap_resource. Taking renamings into account. – &pdev->dev vs dev. 26
  • 27. Conclusion Coccinelle Define and perform arbitrary transformations across a code base. Reasonable performance in most cases. Boolean example takes 7 minutes on a 4 core laptop. Impact: Over 1000 patches in Linux based on Coccinelle. Over 40 semantic patches in linux/scripts/coccinelle. http://coccinelle.lip6.fr/ http://coccinellery.org/