├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── README.md ├── babel.config.js ├── docs ├── debuggers │ ├── _category_.json │ └── lldb.md ├── dynamic-analyzers │ ├── _category_.json │ ├── sanitizers.md │ └── valgrind.md ├── home.md ├── methodology.md └── static-analyzers │ ├── _category_.json │ ├── clang_static_analyzer.md │ └── gcc_static_analyzer.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── scripts └── cmd.sh ├── sidebars.js ├── src ├── components │ ├── Asciinema.tsx │ ├── Godbolt.tsx │ └── Iframe.tsx ├── css │ └── custom.css └── theme │ └── MDXComponents.ts ├── static ├── .nojekyll ├── ascii │ ├── lldb_breakpoints.cast │ ├── lldb_control.cast │ ├── lldb_gui.cast │ ├── lldb_process_args.cast │ ├── lldb_process_start.cast │ └── lldb_watchpoints.cast ├── img │ ├── favicon.ico │ ├── logo.png │ └── logo.svg ├── reports │ ├── codechecker │ │ ├── ctu.c_clangsa_b47ff9b5670acdc84df8e3c892e913b4.plist.html │ │ ├── index.html │ │ └── statistics.html │ └── scan-build.html └── screenshots │ └── lldb_vscode.png └── tsconfig.json /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | deploy: 10 | name: Deploy to GitHub Pages 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: 16.x 17 | cache: npm 18 | 19 | - name: Install dependencies 20 | run: npm ci 21 | - name: Build website 22 | run: npm run build 23 | 24 | - name: Deploy to GitHub Pages 25 | uses: peaceiris/actions-gh-pages@v3 26 | with: 27 | github_token: ${{ secrets.GITHUB_TOKEN }} 28 | publish_dir: ./build 29 | user_name: github-actions[bot] 30 | user_email: 41898282+github-actions[bot]@users.noreply.github.com 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # >> https://sebastienwae.github.io/debugging-42/ 2 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/debuggers/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Debuggers", 3 | "position": 3, 4 | "link": { 5 | "type": "generated-index" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docs/debuggers/lldb.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: LLDB introduction 4 | --- 5 | 6 | # LLDB 7 | 8 | [LLDB](https://lldb.llvm.org/) is a debugger that allows you to monitor and change a program as it is running. For example, it allows you to pause a process when a condition is reached, execute a function step by step or even change the value of a variable at runtime. 9 | 10 | You can use it for a wild variety of tasks. It even has an API for the more complex use case. We will, however, only cover the basis needed to get you started. Checkout the [resources](/debuggers/lldb#resources) if you want to dive deeper. 11 | 12 | ## Starting LLDB 13 | 14 | LLDB works by targeting a specific process. Usually, it is done by connecting to an existing one, but you do not have the required rights to do so on 42’s computers. 15 | 16 | The other way is to make LLDB start the process itself. You can define the program to launch when starting the `lldb` command or with the `target create` command once you are in the console. 17 | 18 | ```shell 19 | $ lldb my_program 20 | # or 21 | $ lldb 22 | (lldb) target create my_program 23 | ``` 24 | 25 | Once the program to run is defined, you can start it by running the `process launch` command, or the aliases `r` or `run`. 26 | 27 | ```shell 28 | (lldb) process launch 29 | # or 30 | (lldb) run 31 | # or 32 | (lldb) r 33 | ``` 34 | 35 | ### Arguments 36 | 37 | Passing arguments to your program if often required, you can do it by adding `--` after the LLDB command and options. 38 | 39 | ```shell 40 | $ lldb -- my_program arg1 arg2 41 | # or 42 | (lldb) process launch -- my_program arg1 arg2 43 | ``` 44 | 45 | It is also possible to add them through the `settings` command once you are in the console. 46 | 47 | ```shell 48 | (lldb) settings set -- target.run-args "hello world" 49 | ``` 50 | 51 | ### Examples 52 | 53 | 54 |
55 | 56 | 57 | ## Help & Documentation 58 | 59 | LLDB has a great documentation system available at anytime with the `help` command. By default, it will dump the list of all available commands and some relevant aliases. 60 | 61 | ```shell 62 | (lldb) help 63 | ``` 64 | To get more information on a specific command or alias, you can pass it as an argument. 65 | 66 | ```shell 67 | (lldb) help source 68 | Commands for examining source code described by debug information for the current target process. 69 | 70 | Syntax: source [] 71 | 72 | The following subcommands are supported: 73 | 74 | info -- Display source line information for the current target process. Defaults to instruction pointer in current stack frame. 75 | list -- Display source code for the current target process as specified by options. 76 | 77 | For more help on any particular subcommand, type 'help '. 78 | ``` 79 | 80 | ```shell 81 | (lldb) help r 82 | Launch the executable in the debugger. 83 | 84 | Syntax: r [] 85 | 86 | Command Options Usage: 87 | r [] 88 | 89 | 90 | 'r' is an abbreviation for 'process launch -c /usr/bin/zsh --' 91 | ``` 92 | 93 | ### Suggestions 94 | 95 | Like ZSH or Bash, LLDB has a suggestion system available with the `TAB` key. If you want to know which commands, options or arguments is available at anytime, press the `TAB` key and it will show you multiples suggestions or it will automatically complete what you typed if it is the only option. 96 | 97 | ```shell 98 | (lldb) process con 99 | Available completions: 100 | connect -- Connect to a remote debug service. 101 | continue -- Continue execution of all threads in the current process. 102 | ``` 103 | 104 | ### Apropos 105 | 106 | If you do not remember the exact name of what you are searching for, the `apropos` command will search all the documentation for the specified word(s). 107 | 108 | ```shell 109 | (lldb) apropos remove 110 | The following commands may relate to 'remove': 111 | renderscript kernel breakpoint all -- Automatically sets a breakpoint on all renderscript kernels that are or will be loaded. 112 | Disabling option means breakpoints will no longer be set on any kernels loaded in the future, but does not remove currently set breakpoints. 113 | settings remove -- Remove a value from a setting, specified by array index or dictionary key. 114 | thread plan prune -- Removes any thread plans associated with currently unreported threads. Specify one or more TID's to remove, or if no TID's are provides, remove threads for all unreported threads 115 | ``` 116 | 117 | ## Inspect & Modify 118 | 119 | LLDB also gives you the ability to inspect the state of a process and even to change it. 120 | 121 | ### Variables 122 | 123 | You can use the `frame variable` or `v` command to inspect the variables in the current stack frame. 124 | 125 | ```shell 126 | (lldb) frame variable 127 | (char *) str = 0x00007fffffffc70d "hell0 w0rld" 128 | (size_t) len = 11 129 | ``` 130 | 131 | Simple operations like &, *, ->, [] can be used to access the variables values. 132 | 133 | ```shell 134 | (lldb) frame variable str[3] 135 | (char) str[3] = 'l' 136 | ``` 137 | 138 | You can access global variables with the `--show-globals` flag. 139 | 140 | The `--format` option can change how the values are displayed. 141 | 142 | ```shell 143 | # Display the value in hexadecimal 144 | (lldb) frame variable --format hex len 145 | (size_t) len = 0x000000000000000b 146 | # Display the value in binary 147 | (lldb) frame variable --format binary len 148 | (size_t) len = 0b0000000000000000000000000000000000000000000000000000000000001011 149 | ``` 150 | 151 | The list of all the formats can be found with the `help format` command. 152 | 153 | ### Expressions 154 | 155 | You can use expressions with the `expressions` or `e` commands. They allow you to execute arbitrary code in the current stack frame of the process. You can change the value of any variable, create new ones, call functions, etc. without re-compiling or restarting the program. 156 | 157 | The value returned by an expression is stored in a variable, in the format `$n` and can be reused. 158 | 159 | ```shell 160 | (lldb) expression 1 + 1 161 | (int) $0 = 2 162 | (lldb) expression $0 + 1 163 | (int) $1 = 3 164 | (lldb) expression $0 + $1 165 | (int) $2 = 5 166 | ``` 167 | 168 | ```shell 169 | # Get the value of the variable str 170 | (lldb) expression str 171 | (char *) $0 = 0x00007fffffffc70d "hell0 w0rld" 172 | # Call the funtion sprintf 173 | (lldb) expression (int)sprintf(str, "hello world") 174 | (int) $1 = 11 175 | (lldb) v str 176 | (char *) str = 0x00007fffffffc70d "hello world" 177 | # Change the value of the variable str 178 | (lldb) expression str = "hi earth" 179 | (char *) $2 = 0x00007ffff7fbe420 "hi earth" 180 | (lldb) v str 181 | (char *) str = 0x00007ffff7fbe420 "hi earth" 182 | ``` 183 | 184 | You can even write multi-line expressions by pressing the `Return` after an empty expression. 185 | 186 | ```shell 187 | (lldb) expression 188 | Enter expressions, then terminate with an empty line to evaluate: 189 | 1: line 1 190 | 2: line 2 191 | 3: ... 192 | ``` 193 | 194 | ## Stopping the process 195 | 196 | In order to inspect or change the state of your program, you will first need to stop it. 197 | 198 | By default, this will only happen if an exception is raised or a stopping signal such as SIGKILL is received. If you want to stop the program at a specific point in the program, you will need to use breakpoints through the `breakpoint` command or its alias `br`. 199 | 200 | If you are stuck in a loop or if you want to stop the program right away, you can use the press `CTRL + c` to make it stop at the next instruction. 201 | 202 | ### Adding breakpoints 203 | 204 | Breakpoints can be added to various types of targets, such as functions, lines of code, regex. 205 | 206 | You can find the list of all the options with the `help breakpoint set` command, but the most common ones are: 207 | 208 | ```shell 209 | # Set a breakpoint in file main.c at line 20 and column 10 210 | (lldb) breakpoint set --joint-specifier main.c:20:10 211 | # Set a breakpoint on the function main 212 | (lldb) breakpoint set --name main 213 | ``` 214 | 215 | The alias `b` is a powerful way to quickly add various types of breakpoints, as it will infer its type based on the arguments you pass. A list of all the argument format is available with the `help b` command. 216 | 217 | ```shell 218 | # Set a breakpoint in file main.c at line 20 and column 10 219 | (lldb) b main.c:20:10 220 | # Set a breakpoint on the function main 221 | (lldb) b main 222 | # Set a breakpoint on the address 0x1234000 223 | (lldb) b 0x1234000 224 | ``` 225 | 226 | ### Conditions 227 | 228 | Sometimes you might want your breakpoints to only be triggered when a certain condition is met. 229 | 230 | The easiest way is with the `--ignore-count` option. This will allow you to set the number of time the breakpoint must be hit before it is triggered. 231 | 232 | ```shell 233 | // main.c 234 | int main(void) { 235 | for (int i = 0; i < 10; i++) { 236 | printf("%d\n", i); 237 | } 238 | } 239 | ``` 240 | 241 | ```shell 242 | # The breakpoint will be triggered after 2 loop, for when i == 2 243 | (lldb) breakpoint set --line 4 --ignore-count 2 244 | ``` 245 | 246 | The other way is through the uses of [expressions](/debuggers/lldb#expressions) and the `--condition` option. 247 | 248 | ```shell 249 | # The breakpoint will be triggered when i == 2 250 | (lldb) breakpoint set --line 4 --condition 'i + 5 == 7' 251 | # The breakpoint will be triggered when the first argument passed to the program is 'hello' 252 | (lldb) breakpoint set --name main --condition 'strcmp(argv[1], "hello") == 0' 253 | ``` 254 | 255 | ### Watchpoints 256 | 257 | Watchpoints are a special breakpoint that will trigger when the value of a variable or an address is changed or read. 258 | 259 | You create them with the `watchpoint set` command. Instead of defining a line or function, you define a variable or an address. 260 | 261 | `watchpoint set variable` takes the name of a variable in the current frame, and `watchpoint set expression` takes an [expression](/debuggers/lldb#expressions) used to evaluate the address. 262 | 263 | ```shell 264 | (lldb) watchpoint set variable -w read_write foo 265 | (lldb) watchpoint set expression -w write -s 1 -- bar + 32 266 | ``` 267 | 268 | Both `variable` and `expression` can take a `--size` flag to define the number of bytes to watch, and a `--watch` flag that can be `read`, `write` or `read_write` to define what kind of operation to watch for. 269 | 270 | ### Managing breakpoints 271 | 272 | Most commands that act on breakpoints will require their ID as an argument, in order to get it or if you want to see all the existing breakpoints, you can use the `breakpoint list` command. 273 | 274 | ```shell 275 | (lldb) breakpoint list 276 | ``` 277 | 278 | When creating breakpoints, you have the possibility to name them with the `--breakpoint-name` option, which can later be used to more easily find them or to remember why you added them. 279 | 280 | ```shell 281 | (lldb) breakpoint set --line 4 --breakpoint-name "for_loop" 282 | ``` 283 | 284 | #### Modifying breakpoints 285 | 286 | Existing breakpoints can be modified with the `breakpoint modify` command. 287 | 288 | The main purpose of this command is to change the condition of a breakpoint. 289 | 290 | ```shell 291 | # Add a condition to the breakpoint with the ID 1 292 | (lldb) breakpoint modify --condition 'i + 5 == 7' 1 293 | # Remove the condition from the last added breakpoint 294 | (lldb) breakpoint modify --condition '' 295 | ``` 296 | 297 | #### Removing breakpoints 298 | 299 | When you no longer need a breakpoint, you can remove it with the `breakpoint remove` command. 300 | 301 | ```shell 302 | # Remove the breakpoint with the ID 1 303 | (lldb) breakpoint remove 1 304 | # Remove all the existing breakpoints 305 | (lldb) breakpoint remove 306 | ``` 307 | 308 | If instead you still want to keep the breakpoint for future use, you can disable it with the `breakpoint disable` command and then use the `breakpoint enable` command to re-enable it. 309 | 310 | ```shell 311 | # Disable the breakpoint with the ID 1 312 | (lldb) breakpoint disable 1 313 | # Disable all the existing breakpoints 314 | (lldb) breakpoint disable 315 | # Enable the breakpoint with the ID 1 316 | (lldb) breakpoint enable 1 317 | ``` 318 | 319 | #### Saving breakpoints 320 | 321 | When you quit LLDB all your breakpoints will be lost. If you want to re-use or share them with others, you can save them to a file with the `breakpoint write` command. 322 | 323 | ```shell 324 | (lldb) breakpoint write --file my_breakpoints 325 | ``` 326 | 327 | ```shell 328 | (lldb) breakpoint write --append --file my_breakpoints 329 | ``` 330 | 331 | ### Examples 332 | 333 | 334 |
335 | 336 | 337 | ## Controlling the process 338 | 339 | Once you have stopped the process, you can control it with the `thread` commands: 340 | 341 | - `thread step-in` or `s` will step into the next function call. 342 | - `thread step-out` or `finish` will step out of the current function. 343 | - `thread step-over` or `n` will go to the next instruction, but will not step into functions. 344 | - `thread continue` or `c` will continue the process until the next breakpoint or the end of the program. 345 | 346 | Pressing the `Return` key with no command will re-execute the last command you used. 347 | 348 | If at any point you want to see where you are in the program, you can use the `process status` command. 349 | 350 | ```shell 351 | (lldb) process status 352 | Process 11582 stopped 353 | * thread #1, name = 'my_program', stop reason = step over 354 | frame #0: 0x00005555555551c0 my_program`ft_strlen(str="hell0 w0rld") at main.c:12:10 355 | 9 356 | 10 size_t ft_strlen(char *str) { 357 | 11 size_t len = 0; 358 | -> 12 for (; str[len]; ++len); 359 | 13 return len; 360 | 14 } 361 | 15 362 | ``` 363 | 364 | ### Call stack 365 | 366 | On top of being able to control the process, LLDB also allows you to see and move inside the call stack. 367 | 368 | The `thread backtrace` command will show you the current call stack. 369 | 370 | ```shell 371 | (lldb) thread backtrace 372 | * thread #1, name = 'my_program', stop reason = breakpoint 2.1 373 | * frame #0: 0x000055555555515a my_program`is_alpha(c='e') at main.c:5:8 374 | frame #1: 0x0000555555555281 my_program`main(argc=2, argv=0x00007fffffffc308) at main.c:25:11 375 | frame #2: 0x00007ffff7c29290 libc.so.6`___lldb_unnamed_symbol3123 + 128 376 | frame #3: 0x00007ffff7c2934a libc.so.6`__libc_start_main + 138 377 | frame #4: 0x0000555555555075 my_program`_start at start.S:115 378 | ``` 379 | 380 | You can then use the `frame select` command to select which frame you want to see. 381 | 382 | ```shell 383 | (lldb) frame select 1 384 | ``` 385 | 386 | This is extremely useful to understand what appended before the point you currently are in the program and find the cause of the broken state you are currently in. 387 | 388 | The `up` and `down` commands will also move the call stack up and down. 389 | 390 | ### Examples 391 | 392 | 393 | 394 | 395 | ## GUI mode 396 | 397 | LLDB has GUI mode, it is not the most pleasant way to interact with it but it can be useful if you struggle with using the default console. 398 | 399 | You can enable it by typing the `gui` command on the LLDB console. Press `h` to bring up the help menu or `Escape` to go back to the console. 400 | 401 | ```shell 402 | (lldb) gui 403 | ``` 404 | 405 | 406 | 407 | ## Visual Studio Code 408 | 409 | VSCode can interact with LLDB trough the [Microsoft C/C++ extention](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools). 410 | 411 | It allows you to add or remove breakpoints, inspect variable or the call stack from within your IDE while still keeping access to the LLDB console. 412 | 413 | Read [VSCode documenation on debugging](https://code.visualstudio.com/docs/editor/debugging) for more information on how to use it. 414 | 415 | ![lldb in visual studio code](/screenshots/lldb_vscode.png) 416 | 417 | ## Resouces 418 | 419 | - https://lldb.llvm.org/use/tutorial.html 420 | - Advanced Apple Debugging & Reverse Engineering - Derek Selander 421 | - https://developer.apple.com/videos/play/wwdc2019/429/ 422 | -------------------------------------------------------------------------------- /docs/dynamic-analyzers/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Dynamic Analyzers", 3 | "position": 4, 4 | "link": { 5 | "type": "generated-index" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docs/dynamic-analyzers/sanitizers.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: Sanitizers introduction 4 | --- 5 | 6 | # Sanitizers 7 | 8 | :::info 9 | Besides UndefinedBehaviorSanitizer, multiple sanitizers cannot be used at the same time. 10 | ::: 11 | 12 | Sanitizers is a Google project that is part of both Clang and GCC. It encompasses multiple tools that can help you detect and fix hard to find bugs. 13 | 14 | It works by adding extra instructions at compile time and a runtime library. It will require you to re-compile your project, but [it can find more bugs](https://llvm.org/devmtg/2011-11/Serebryany_FindingRacesMemoryErrors.pdf) than tools such as Valgrind and has a lower performance impact on your program. 15 | 16 | More sanitizers, such as [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html), are available but not covered here as they are not macOS compatible. 17 | 18 | ## AddressSanitizer 19 | 20 | AddressSanitizer can detect various memory errors, such as: 21 | - Out-of-bounds accesses to heap, stack and global 22 | - Use-after-free 23 | - Use-after-scope 24 | - Double-free, invalid free 25 | 26 | You can enable it with the `-fsanitize=address` flag. 27 | 28 | It is also recommended to add the `-fno-omit-frame-pointer` and `-fno-optimize-sibling-calls` flags to get more detailed stack traces. 29 | 30 | ### Example 31 | 32 | 33 | 34 | ## LeakSanitizer 35 | 36 | :::info 37 | LeakSanitizer does not work with the LLVM shipped by Apple, you will have to [install](/#setup) a newer version with Homebrew. 38 | ::: 39 | 40 | LeakSanitizer will show you memory leaks. It is included in AdressSanitizer and enabled by default on Linux, on macOS you will need to enable it explicitly. 41 | 42 | You can toggle it by changing the value of `detect_leaks` to `0` to disable it or `1` to enable it , in the `ASAN_OPTIONS` variable of your environment. 43 | 44 | ```shell 45 | $ export ASAN_OPTIONS=detect_leaks=1 46 | $ export ASAN_OPTIONS=detect_leaks=0 47 | ``` 48 | 49 | You can also use the `-fsanitize=leak` flag to use it as a standalone. 50 | 51 | ### Example 52 | 53 | 54 | 55 | ## UndefinedBehaviorSanitizer 56 | 57 | UndefinedBehaviorSanitizer will show you bugs such as: 58 | - Array subscript out of bounds 59 | - Dereferencing misaligned or null pointers 60 | - Signed integer overflow 61 | 62 | You can find the list of all checks in the [documentation](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks) 63 | 64 | You can enable it with the `-fsanitize=undefined` flag. 65 | 66 | It is the only sanitizer that can be used with other sanitizers. You can do it by separating them with a comma `-fsanitize=address,undefined`. 67 | 68 | ### Example 69 | 70 | 71 | 72 | ## ThreadSanitizer 73 | 74 | ThreadSanitizer will detect data races in your program. 75 | 76 | You can enable it with the `-fsanitize=thread` flag. 77 | 78 | ### Example 79 | 80 | 81 | 82 | ## Resources 83 | 84 | - https://github.com/google/sanitizers/wiki 85 | - https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early 86 | - https://clang.llvm.org/docs/AddressSanitizer.html 87 | - https://clang.llvm.org/docs/LeakSanitizer.html 88 | - https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html 89 | - https://clang.llvm.org/docs/ThreadSanitizer.html 90 | -------------------------------------------------------------------------------- /docs/dynamic-analyzers/valgrind.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: Valgrind introduction 4 | --- 5 | 6 | # Valgrind 7 | 8 | Even though [Valgrind](https://valgrind.org/) is mostly used to find memory leaks, it can do a lot more. It is a made of multiple tools that can help you find various types of errors in your code. 9 | 10 | It works by running your program on a synthetic CPU and dynamically re-compiling it. You do not need to change or re-compile your program to make it compatible, but it comes at the cost of slowing its execution by a factor or 5 to 100. 11 | 12 | ## macOS 13 | 14 | Valgrind is currently [only supporting macOS up to High Sierra](https://valgrind.org/docs/manual/dist.news.html) (10.12). Thankfully there is a fork that works with macOS Catalina (10.15). 15 | 16 | https://github.com/LouisBrunner/valgrind-macos 17 | 18 | The easiest way to install it is through Homebrew: 19 | 20 | ```shell 21 | $ brew tap LouisBrunner/valgrind 22 | $ brew install --HEAD LouisBrunner/valgrind/valgrind 23 | ``` 24 | 25 | Be careful that [not all features are working](https://github.com/LouisBrunner/valgrind-macos#status). 26 | 27 | ## MemCheck 28 | 29 | MemCheck is Valgrind default tool. It’s often only used to check memory leaks, but it can detect a lot of different type of memory error such as: 30 | - Out-of-bounds accesses to heap 31 | - Use-after-free 32 | - Using undefined values 33 | 34 | To not miss any leak or error and get more information, I suggest you to always run MemCheck with the flags: 35 | ```shell 36 | --leak-check=full --show-leak-kinds=all -s 37 | ``` 38 | 39 | The error messages can be cryptic at first, but the documentation goes through [several examples](https://valgrind.org/docs/manual/mc-manual.html#mc-manual.errormsgs). Use them as a reference until you are familiar with them. 40 | 41 | ### Example 42 | 43 | ```c 44 | // leaks.c 45 | #include 46 | 47 | void f(void) { 48 | int* x = malloc(10 * sizeof(int)); 49 | x[10] = 0; 50 | } 51 | 52 | int main(void) { 53 | f(); 54 | return 0; 55 | } 56 | ``` 57 | 58 | ```shell 59 | $ clang -g leaks.c -o leaks 60 | $ valgrind --leak-check=full --show-leak-kinds=all ./leaks 61 | ==40468== Memcheck, a memory error detector 62 | ==40468== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. 63 | ==40468== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info 64 | ==40468== Command: ./leaks 65 | ==40468== 66 | ==40468== Invalid write of size 4 67 | ==40468== at 0x10915A: f (main.c:5) 68 | ==40468== by 0x109183: main (main.c:9) 69 | ==40468== Address 0x4a8e068 is 0 bytes after a block of size 40 alloc'd 70 | ==40468== at 0x4845888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 71 | ==40468== by 0x109151: f (main.c:4) 72 | ==40468== by 0x109183: main (main.c:9) 73 | ==40468== 74 | ==40468== 75 | ==40468== HEAP SUMMARY: 76 | ==40468== in use at exit: 40 bytes in 1 blocks 77 | ==40468== total heap usage: 1 allocs, 0 frees, 40 bytes allocated 78 | ==40468== 79 | ==40468== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1 80 | ==40468== at 0x4845888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 81 | ==40468== by 0x109151: f (main.c:4) 82 | ==40468== by 0x109183: main (main.c:9) 83 | ==40468== 84 | ==40468== LEAK SUMMARY: 85 | ==40468== definitely lost: 40 bytes in 1 blocks 86 | ==40468== indirectly lost: 0 bytes in 0 blocks 87 | ==40468== possibly lost: 0 bytes in 0 blocks 88 | ==40468== still reachable: 0 bytes in 0 blocks 89 | ==40468== suppressed: 0 bytes in 0 blocks 90 | ==40468== 91 | ==40468== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 92 | ==40468== 93 | ==40468== 1 errors in context 1 of 2: 94 | ==40468== Invalid write of size 4 95 | ==40468== at 0x10915A: f (main.c:5) 96 | ==40468== by 0x109183: main (main.c:9) 97 | ==40468== Address 0x4a8e068 is 0 bytes after a block of size 40 alloc'd 98 | ==40468== at 0x4845888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 99 | ==40468== by 0x109151: f (main.c:4) 100 | ==40468== by 0x109183: main (main.c:9) 101 | ==40468== 102 | ==40468== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 103 | ``` 104 | 105 | ## Resources 106 | 107 | - https://valgrind.org 108 | - https://valgrind.org/docs/manual/manual.html 109 | -------------------------------------------------------------------------------- /docs/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: / 3 | sidebar_position: 1 4 | description: Debugging resources for 42 5 | --- 6 | 7 | # Home 8 | 9 | :::info 10 | The content is written with a focus on macOS as it is the OS used at 42 Mulhouse, it should mostly work the same on Linux. 11 | ::: 12 | 13 | The goal of this website is to provide an introduction to the methods and tools you can use to debug your program during the common core of 42 and beyond. 14 | 15 | You will not find in-depth information on the inner working of the tools or their advanced options, for that dig on your own and RTFM. 16 | 17 | The tools presented here are very useful, but they are not magic. They are themselves subject to bugs and cannot be trusted at 100%. They are not a replacement for the understanding of your code and the machine they are running on. 18 | 19 | I would also suggest spending more time understanding the methods to debug a program than the tools to do so. They will be relevant with most of the programming languages you will encounter. 20 | 21 | This project is a work in progress. You can take part in its improvement by opening issues or sending pull request to [its repository](https://github.com/SebastienWae/debugging-42). 22 | 23 | ## Setup 24 | Before continuing, here are some preliminary steps you should do to set up your machine. 25 | 26 | ### Homebrew 27 | 28 | [Homebrew](https://brew.sh) is a [package manager](https://en.wikipedia.org/wiki/Package_manager), you will use it to install, manage and update software on your machine. 29 | 30 | Since you do not have the admin rights on 42's computers and the disk space is limited I suggest you to use this script to install it in the goinfre of the machine you are using. 31 | 32 | https://github.com/omimouni/42homebrew 33 | 34 | ```shell 35 | $ curl -fsSL https://raw.githubusercontent.com/omimouni/42homebrew/master/install-goinfre.sh | zsh 36 | ``` 37 | 38 | ### LLVM 39 | 40 | [LLVM](https://llvm.org/) is an open source compiler and toolchain that include [Clang](https://clang.llvm.org/). By default, macOS ship with an old version of it, you can use Homebrew to install the latest version, this will give you access to better tooling, performance and error handling. 41 | 42 | ```shell 43 | $ brew install LLVM 44 | ``` 45 | 46 | To be able to use it you will have to update the `PATH` variable. In your `.zshrc` add the following line: 47 | 48 | ```shell 49 | export PATH=~/goinfre/.brew/opt/llvm/bin:$PATH 50 | ``` 51 | 52 | When you type `clang` in your terminal you will use the latest version, the one you just installed. You can still use `cc` to access the default version (required for your projects). 53 | 54 | ## Debug information 55 | 56 | To have more accurate information with the tools, you must generate the [debug information](https://llvm.org/docs/SourceLevelDebugging.html) while compiling your program. 57 | 58 | To do that, add the `-g` flag when compiling. 59 | 60 | This will add the debug information to the output file or in a `.dSYM` file for macOS. 61 | 62 | As it does not load these informations when running normally, your program performance will not be affected. 63 | 64 | More flags are available to output these informations, such as `-g3`, `-ggdb`, you can find more details in your [compiler documentation](https://clang.llvm.org/docs/UsersManual.html#controlling-debug-information). 65 | 66 | ### Example 67 | 68 | Without debug information: 69 | ```shell {3} 70 | ==41461==The signal is caused by a WRITE memory access. 71 | ==41461==Hint: address points to the zero page. 72 | #0 0x10d3a4f4c in main+0x5c (a.out:x86_64+0x100003f4c) 73 | #1 0x7fff72f3fcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8) 74 | ``` 75 | 76 | With debug information: 77 | ```shell {3} 78 | ==41523==The signal is caused by a WRITE memory access. 79 | ==41523==Hint: address points to the zero page. 80 | #0 0x106f73f4c in main test.c:7 81 | #1 0x7fff72f3fcc8 in start+0x0 (libdyld.dylib:x86_64+0x1acc8) 82 | ``` 83 | -------------------------------------------------------------------------------- /docs/methodology.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | description: Debugging methodology 4 | --- 5 | 6 | # Methodology 7 | 8 | This section is not ready yet... 9 | 10 | In the meantime, I suggest you check out [The Debugging Book](https://www.debuggingbook.org). It provides very good information and interactive notebooks. The examples are in Python, but the knowledge can be applied in almost any other language. 11 | 12 | You can also read the following book: 13 | - Effective Debugging - Diomidis Spinellis 14 | - Debugging - David J Agans 15 | - Why Programs Fail - Andreas Zeller 16 | -------------------------------------------------------------------------------- /docs/static-analyzers/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Static Analyzers", 3 | "position": 5, 4 | "link": { 5 | "type": "generated-index" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docs/static-analyzers/clang_static_analyzer.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | description: Clang static analyzer introduction 4 | --- 5 | 6 | # Clang Static Analyzer 7 | 8 | :::caution 9 | Static analyzer are not magic, they will not catch all errors and can report false positives. 10 | ::: 11 | 12 | [Clang Static Analyzer](https://clang-analyzer.llvm.org/) can help you find issues such as: 13 | - Uninitialized arguments 14 | - Division by zero 15 | - Null function pointer 16 | - Dereferences of null pointers 17 | 18 | On top of the default checker, you can also toggle some experimental checkers that can help find your more bugs. For a list of all options refer to the [Clang manual](https://clang.llvm.org/docs/analyzer/checkers.html). 19 | 20 | You can use Clang static analyzer directly through Clang, but the more ergonomic way is with tools such as [Scan-Build](https://clang-analyzer.llvm.org/scan-build.html) or [CodeChecker](https://codechecker.readthedocs.io/en/latest/). 21 | 22 | ## Scan-Build 23 | 24 | Scan-Build is the old but also simplest way to use Clang Static Analyzer, no installation needed as it's part of the LLVM project. 25 | 26 | 27 | ### Scanning files 28 | 29 | It works by replacing the `CC` of `CXX` variable in your build system. No need to change your Makefile, you only need to pass your build command as an argument: 30 | 31 | ```shell 32 | $ scan-build make 33 | ``` 34 | 35 | For a smaller project, you can also pass your compilation command: 36 | 37 | ```shell 38 | $ scan-build gcc -c my_code.c 39 | ``` 40 | 41 | ### Viewing the results 42 | 43 | The terminal output of `scan-build` is quite sparse, but you can generate HTML files that give you more information. 44 | 45 | By default, the files are saved in the `/tmp` directory and can be opened with the `scan-view` command. You can also choose a different directory with the `-o` flag or automatically open the HTML files with the `-V` flag. 46 | 47 | ### Example 48 | 49 | ```c 50 | // bad_code.c 51 | #include 52 | 53 | struct link { struct link *next; }; 54 | 55 | void free_a_list_badly(struct link *n) 56 | { 57 | while (n) { 58 | free(n); 59 | n = n->next; 60 | } 61 | } 62 | ``` 63 | 64 | ```shell 65 | $ scan-build clang -c bad_code.c 66 | scan-build: Using '/usr/bin/clang-13' for static analysis 67 | bad_code.c:9:9: warning: Use of memory after it is freed [unix.Malloc] 68 | n = n->next; 69 | ^~~~~~~ 70 | 1 warning generated. 71 | scan-build: Analysis run complete. 72 | scan-build: 1 bug found. 73 | scan-build: Run 'scan-view /tmp/scan-build-2022-06-19-123309-28897-1' to examine bug reports. 74 | ``` 75 | 76 | 12 | ); 13 | } 14 | 15 | export default Godbolt; 16 | -------------------------------------------------------------------------------- /src/components/Iframe.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import BrowserOnly from '@docusaurus/BrowserOnly'; 3 | import useBaseUrl from '@docusaurus/useBaseUrl'; 4 | 5 | type IframeProps = { 6 | url: string 7 | }; 8 | const Iframe = ({ url }: IframeProps) => { 9 | return ( 10 | 11 | {() => { 12 | return ( 13 |