├── .gitignore ├── LICENSE ├── README.md ├── Vagrantfile ├── article_opensourcecom └── article.md ├── talk ├── Makefile ├── beamercolorthememetropolis-highcontrast.sty ├── beamercolorthememetropolis.sty ├── beamerfontthememetropolis.sty ├── beamerinnerthememetropolis.sty ├── beamerouterthememetropolis.sty ├── beamerthememetropolis.sty ├── figures │ ├── punch_card_stack.jpg │ └── tx0.jpg ├── pgfplotsthemetol.sty ├── talk.pdf ├── talk.tex └── talk_lca2018.pdf ├── talk_dbg ├── Cargo.lock ├── Cargo.toml └── src │ ├── main.rs │ ├── ptrace │ └── mod.rs │ └── target │ └── mod.rs ├── test_program ├── Makefile └── main.c └── vagrant_bootstrap.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | talk_dbg/_final/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | /target/ 13 | **/*.rs.bk 14 | Cargo.lock 15 | 16 | ## LaTeX 17 | talk/talk.aux 18 | talk/talk.vrb 19 | talk/talk.log 20 | talk/talk.nav 21 | talk/talk.out 22 | talk/talk.snm 23 | talk/talk.synctex.gz 24 | talk/talk.toc 25 | _minted-talk/ 26 | 27 | ## Vagrant 28 | .vagrant/ 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Levente Kurusa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # debugger-talk 2 | Resources for the debugger talk 3 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "ubuntu/xenial64" 3 | config.vm.provision :shell, path: "vagrant_bootstrap.sh" 4 | 5 | # Required for NFS to work, pick any local IP 6 | config.vm.network :private_network, ip: '192.168.50.50' 7 | 8 | # Use NFS for shared folders for better performance 9 | config.vm.synced_folder '.', '/vagrant', nfs: true 10 | end 11 | -------------------------------------------------------------------------------- /article_opensourcecom/article.md: -------------------------------------------------------------------------------- 1 | # Let’s Write a Debugger! 2 | ## A talk at linux.conf.au 2018 3 | 4 | ### Introduction 5 | A debugger is one of those pieces of software that most, if not every, developer uses at least once during their software engineering career, but how many of you actually know how they work? During my talk in Sydney, at linux.conf.au 2018 I will be talking about writing a debugger from scratch... in Rust! 6 | 7 | In this article, I use the terms debugger/tracer interchangeably. “Tracee” refers to the process being traced by the tracer. 8 | 9 | ### ptrace system call 10 | Most debuggers heavily rely on a system call known as `ptrace(2)`, which has the prototype: 11 | 12 | ``` 13 | long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data); 14 | ``` 15 | 16 | This is a system call that can manipulate almost all aspects of a process, however before the debugger can attach to a process, the “tracee” has to call `ptrace` with the request `PTRACE_TRACEME`. This tells Linux that it is legitimate for the parent to attach via `ptrace` to this process. But... how do we coerce a process into calling `ptrace`? Easy-peasy! `fork/execve` provides an easy way of calling `ptrace` after `fork` but before the tracee is really started using `execve`. Conveniently, `fork` will also return the `pid` of the tracee, which is required for using `ptrace` later. 17 | 18 | Now that the tracee can be traced by the debugger, important changes take place: 19 | 20 | * everytime a signal is delivered to the tracee, it stops and a wait-event is delivered to the tracer that can be captured by the `wait` family of system calls. 21 | * each successful `execve` system call will cause a `SIGTRAP` to be delivered to the tracee (combined with the previous item, this means the tracee is stopped before an `execve` can fully take place). 22 | 23 | Now this means, that once we issued the `PTRACE_TRACEME` request and called the `execve` system call to actually start the program in the tracee, the tracee will immediately stop since `execve` delivers a `SIGTRAP` and that is caught by a wait-event in the tracer. How do we actually continue? As one would expect, `ptrace` has a number of requests that can be used for telling the tracee it's fine to continue: 24 | 25 | * `PTRACE_CONT`: The simplest. The tracee runs until it receives a signal, at which point a wait-event is delivered to the tracer. This is most commonly used to implement “continue-until-breakpoint” and “continue-forever” options of a real-world debugger. We will cover breakpoints later. 26 | * `PTRACE_SYSCALL`: Similar to `PTRACE_CONT`, but stops before a system call is entered, and also before a system call returns to userspace. It can be used in combination with other requests (which we will cover later in this article) to monitor and modify a system call’s arguments, or return value. `strace`, the system call tracer uses this request heavily to figure out what system calls are made by a process. 27 | * `PTRACE_SINGLESTEP`: Pretty self-explanatory if you used a debugger before, this request implements the ability to execute the next instruction but stops immediately after. 28 | 29 | So we can stop the process with a variety of requests, but how do we get the state of the tracee? The state of a process is mostly captured by its registers, so of course `ptrace` has a request to get (or modify!) the registers: 30 | 31 | * `PTRACE_GETREGS`: When a tracee is stopped, this request will give the state of registers as it was when it stopped. 32 | * `PTRACE_SETREGS`: If the tracer has the values of registers from a previous call to `PTRACE_GETREGS`, then it can modify the values in that structure and set the registers to the new values via this request. 33 | * `PTRACE_PEEKUSER` and `PTRACE_POKEUSER`: Allows reading from the tracee’s `USER` area, which holds the registers and other useful information. One can use this to modify a single register, without the more heavyweight `PTRACE_{GET,SET}REGS`. 34 | 35 | Modifying the registers isn’t always sufficient in a debugger. A debugger will sometimes need to read some parts of the memory or even modify it. In GDB, one can use `print` to get the value of a memory location or a variable. `ptrace` has the functionality to implement this: 36 | 37 | * `PTRACE_PEEKTEXT` and `PTRACE_POKETEXT`: Allows reading and writing a word in the address space of the tracee. Of course, the tracee has to be stopped for this to work. 38 | 39 | Real world debuggers also have features like breakpoints and watchpoints. In the next section, we deep-dive into the architectural details of debugging support. For the purposes of the clarity and conciseness, both the talk and this article will consider x86 only. 40 | 41 | ### Architectural support 42 | 43 | `ptrace` is all-cool, but how does it work? In the previous section, we've seen that `ptrace` has quite a bit to do with signals: `SIGTRAP` can delivered during single-stepping, before `execve` and before/after system calls. 44 | Signals can be generated by a number of ways, but we will look at two specific examples that can be used by debuggers to stop a program (effectively creating a breakpoint!) at a given location: 45 | 46 | * *Undefined instructions*: When a process tries to execute an undefined instruction, an exception is raised by the CPU. This exception is handled via a CPU interrupt and a handler corresponding to the interrupt in the kernel is called. This will result in a `SIGILL` being sent to the process. This, in turn, causes the process to stop and the tracer is notified via a wait-event. It can then decide what to do. On x86, an instruction `ud2` is guaranteed to be always undefined. 47 | 48 | * *Debugging interrupt*: The problem with the previous approach is that the `ud2` instruction takes two bytes of machine code. There exists a special instruction that takes one byte and raises an interrupt. It's `int $3` and the machine code is `0xCC`. When this interrupt is raised, the kernel sends a `SIGTRAP` to the process and just as previously, the tracer is notified. 49 | 50 | This is fine, but how do we coerce the tracee to execute these instructions? Easy, `ptrace` has `PTRACE_POKETEXT` which can override a word at a memory location. A debugger would read the original word at the location using `PTRACE_PEEKTEXT` and replace it with `0xCC`, remembering the original byte and the fact that it is a breakpoint in its internal state. Next time the tracee would execute at the location, it is automatically stopped by the virtue of a `SIGTRAP`. The end user of the debugger can then decide how to continue (for instance, inspect the registers). 51 | 52 | Okay, we've covered breakpoints, but what about watchpoints? How does a debugger stop a program when a certain memory location is read or written? Surely, you wouldn't just overwrite every instruction with `int $3` that could read or write some memory location. Meet debug registers, a set of registers designed to fulfill this goal more efficiently: 53 | 54 | * `DR0` to `DR3`: Each of these registers contains an address (a memory location), where the debugger wants to the tracee to stop for some reason. The reason is specified as a bitmask in `DR7`. 55 | * `DR4` and `DR5`: obsolete aliases to `DR6` and `DR7` respectively. 56 | * `DR6`: *Debug status*. Contains information about which of `DR0` to `DR3` caused the debugging exception to be raised. This is used by Linux to figure out the information passed along with the `SIGTRAP` to the tracee. 57 | * `DR7`: *Debug control*. Using the bits in these registers, the debugger can control how the addresses specified in `DR0`-`DR3` are interpreted. A bitmask controls the size of the watchpoint (whether 1, 2, 4 or 8 bytes are monitored) and whether to raise an exception on execution, reading, writing or either of reading and writing. 58 | 59 | Since the debug registers form part of the `USER` area of a process, the debugger can use `PTRACE_POKEUSER` to write values into the debug registers. The debug registers are only relevant to a specific process and are thus restored to the value at preemption before the process regains control of the CPU. 60 | 61 | ### Conclusion 62 | 63 | We've glanced at the iceberg a debugger is: we've covered `ptrace`, went over some of its functionality, then we had a look at how `ptrace` is implemented. Some parts of `ptrace` can be implemented in software, but other parts have to be implemented in hardware otherwise they'd be very expensive or even impossible. 64 | 65 | There's plenty that we didn't cover, of course. Questions, like "how does a debugger know where a variable is in memory?" remain open due to space and time constraints, but I hope you've learned something from this article and if it piqued your interest, then there are plenty of resources available online to learn more! -------------------------------------------------------------------------------- /talk/Makefile: -------------------------------------------------------------------------------- 1 | talk.pdf: talk.tex 2 | latexmk -pdf $< 3 | 4 | clean: 5 | rm $(shell find . -name 'talk.*' | egrep -v 'talk\.tex|talk\.pdf') 6 | 7 | .PHONY: clean 8 | -------------------------------------------------------------------------------- /talk/beamercolorthememetropolis-highcontrast.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `beamercolorthememetropolis-highcontrast.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% beamercolorthememetropolis-highcontrast.dtx (with options: `package') 8 | %% --------------------------------------------------------------------------- 9 | %% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of 10 | %% contributors can be found at 11 | %% 12 | %% https://github.com/matze/mtheme/graphs/contributors 13 | %% 14 | %% and the original template was based on the HSRM theme by Benjamin Weiss. 15 | %% 16 | %% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 17 | %% International License (https://creativecommons.org/licenses/by-sa/4.0/). 18 | %% --------------------------------------------------------------------------- 19 | \NeedsTeXFormat{LaTeX2e} 20 | \ProvidesPackage{beamercolorthememetropolis-highcontrast}[2017/01/23 Metropolis color theme] 21 | \usecolortheme{metropolis} 22 | 23 | \definecolor{mAlert}{HTML}{AD003D} 24 | \definecolor{mExample}{HTML}{005580} 25 | 26 | \setbeamercolor{normal text}{% 27 | fg=black, 28 | bg=white 29 | } 30 | \setbeamercolor{alerted text}{% 31 | fg=mAlert, 32 | } 33 | \setbeamercolor{example text}{% 34 | fg=mExample, 35 | } 36 | \mode 37 | \endinput 38 | %% 39 | %% End of file `beamercolorthememetropolis-highcontrast.sty'. 40 | -------------------------------------------------------------------------------- /talk/beamercolorthememetropolis.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `beamercolorthememetropolis.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% beamercolorthememetropolis.dtx (with options: `package') 8 | %% --------------------------------------------------------------------------- 9 | %% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of 10 | %% contributors can be found at 11 | %% 12 | %% https://github.com/matze/mtheme/graphs/contributors 13 | %% 14 | %% and the original template was based on the HSRM theme by Benjamin Weiss. 15 | %% 16 | %% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 17 | %% International License (https://creativecommons.org/licenses/by-sa/4.0/). 18 | %% --------------------------------------------------------------------------- 19 | \NeedsTeXFormat{LaTeX2e} 20 | \ProvidesPackage{beamercolorthememetropolis}[2017/01/23 Metropolis color theme] 21 | \RequirePackage{pgfopts} 22 | \pgfkeys{ 23 | /metropolis/color/block/.cd, 24 | .is choice, 25 | transparent/.code=\metropolis@block@transparent, 26 | fill/.code=\metropolis@block@fill, 27 | } 28 | \pgfkeys{ 29 | /metropolis/color/background/.cd, 30 | .is choice, 31 | dark/.code=\metropolis@colors@dark, 32 | light/.code=\metropolis@colors@light, 33 | } 34 | \newcommand{\metropolis@color@setdefaults}{ 35 | \pgfkeys{/metropolis/color/.cd, 36 | background=light, 37 | block=transparent, 38 | } 39 | } 40 | \definecolor{mDarkBrown}{HTML}{604c38} 41 | \definecolor{mDarkTeal}{HTML}{23373b} 42 | \definecolor{mLightBrown}{HTML}{EB811B} 43 | \definecolor{mLightGreen}{HTML}{14B03D} 44 | \newcommand{\metropolis@colors@dark}{ 45 | \setbeamercolor{normal text}{% 46 | fg=black!2, 47 | bg=mDarkTeal 48 | } 49 | \usebeamercolor[fg]{normal text} 50 | } 51 | \newcommand{\metropolis@colors@light}{ 52 | \setbeamercolor{normal text}{% 53 | fg=mDarkTeal, 54 | bg=black!2 55 | } 56 | } 57 | \setbeamercolor{alerted text}{% 58 | fg=mLightBrown 59 | } 60 | \setbeamercolor{example text}{% 61 | fg=mLightGreen 62 | } 63 | \setbeamercolor{titlelike}{use=normal text, parent=normal text} 64 | \setbeamercolor{author}{use=normal text, parent=normal text} 65 | \setbeamercolor{date}{use=normal text, parent=normal text} 66 | \setbeamercolor{institute}{use=normal text, parent=normal text} 67 | \setbeamercolor{structure}{use=normal text, fg=normal text.fg} 68 | \setbeamercolor{palette primary}{% 69 | use=normal text, 70 | fg=normal text.bg, 71 | bg=normal text.fg 72 | } 73 | \setbeamercolor{frametitle}{% 74 | use=palette primary, 75 | parent=palette primary 76 | } 77 | \setbeamercolor{progress bar}{% 78 | use=alerted text, 79 | fg=alerted text.fg, 80 | bg=alerted text.fg!50!black!30 81 | } 82 | \setbeamercolor{title separator}{ 83 | use=progress bar, 84 | parent=progress bar 85 | } 86 | \setbeamercolor{progress bar in head/foot}{% 87 | use=progress bar, 88 | parent=progress bar 89 | } 90 | \setbeamercolor{progress bar in section page}{ 91 | use=progress bar, 92 | parent=progress bar 93 | } 94 | \newcommand{\metropolis@block@transparent}{ 95 | \setbeamercolor{block title}{% 96 | use=normal text, 97 | fg=normal text.fg, 98 | bg= 99 | } 100 | \setbeamercolor{block body}{ 101 | bg= 102 | } 103 | } 104 | \newcommand{\metropolis@block@fill}{ 105 | \setbeamercolor{block title}{% 106 | use=normal text, 107 | fg=normal text.fg, 108 | bg=normal text.bg!80!fg 109 | } 110 | \setbeamercolor{block body}{ 111 | use={block title, normal text}, 112 | bg=block title.bg!50!normal text.bg 113 | } 114 | } 115 | \setbeamercolor{block title alerted}{% 116 | use={block title, alerted text}, 117 | bg=block title.bg, 118 | fg=alerted text.fg 119 | } 120 | \setbeamercolor{block title example}{% 121 | use={block title, example text}, 122 | bg=block title.bg, 123 | fg=example text.fg 124 | } 125 | \setbeamercolor{block body alerted}{use=block body, parent=block body} 126 | \setbeamercolor{block body example}{use=block body, parent=block body} 127 | \setbeamercolor{footnote}{fg=normal text.fg!90} 128 | \setbeamercolor{footnote mark}{fg=.} 129 | \setbeamercolor{bibliography entry author}{fg=, bg=} 130 | \setbeamercolor{bibliography entry title}{fg=, bg=} 131 | \setbeamercolor{bibliography entry location}{fg=, bg=} 132 | \setbeamercolor{bibliography entry note}{fg=, bg=} 133 | \metropolis@color@setdefaults 134 | \ProcessPgfPackageOptions{/metropolis/color} 135 | \mode 136 | \endinput 137 | %% 138 | %% End of file `beamercolorthememetropolis.sty'. 139 | -------------------------------------------------------------------------------- /talk/beamerfontthememetropolis.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `beamerfontthememetropolis.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% beamerfontthememetropolis.dtx (with options: `package') 8 | %% --------------------------------------------------------------------------- 9 | %% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of 10 | %% contributors can be found at 11 | %% 12 | %% https://github.com/matze/mtheme/graphs/contributors 13 | %% 14 | %% and the original template was based on the HSRM theme by Benjamin Weiss. 15 | %% 16 | %% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 17 | %% International License (https://creativecommons.org/licenses/by-sa/4.0/). 18 | %% --------------------------------------------------------------------------- 19 | \NeedsTeXFormat{LaTeX2e} 20 | \ProvidesPackage{beamerfontthememetropolis}[2017/01/23 Metropolis font theme] 21 | \RequirePackage{etoolbox} 22 | \RequirePackage{ifxetex} 23 | \RequirePackage{ifluatex} 24 | \RequirePackage{pgfopts} 25 | \ifboolexpr{bool {xetex} or bool {luatex}}{ 26 | \@ifpackageloaded{fontspec}{ 27 | \PassOptionsToPackage{no-math}{fontspec} 28 | }{ 29 | \RequirePackage[no-math]{fontspec} 30 | } 31 | \newcounter{fontsnotfound} 32 | \newcommand{\checkfont}[1]{% 33 | \suppressfontnotfounderror=1% 34 | \font\x = "#1" at 10pt 35 | \selectfont 36 | \ifx\x\nullfont% 37 | \stepcounter{fontsnotfound}% 38 | \fi% 39 | \suppressfontnotfounderror=0% 40 | } 41 | 42 | \newcommand{\iffontsavailable}[3]{% 43 | \setcounter{fontsnotfound}{0}% 44 | \expandafter\forcsvlist\expandafter% 45 | \checkfont\expandafter{#1}% 46 | \ifnum\value{fontsnotfound}=0% 47 | #2% 48 | \else% 49 | #3% 50 | \fi% 51 | } 52 | \iffontsavailable{Fira Sans Light,% 53 | Fira Sans Light Italic,% 54 | Fira Sans,% 55 | Fira Sans Italic}% 56 | {% 57 | \setsansfont[ItalicFont={Fira Sans Light Italic},% 58 | BoldFont={Fira Sans},% 59 | BoldItalicFont={Fira Sans Italic}]% 60 | {Fira Sans Light}% 61 | }{% 62 | \iffontsavailable{Fira Sans Light OT,% 63 | Fira Sans Light Italic OT,% 64 | Fira Sans OT,% 65 | Fira Sans Italic OT}% 66 | {% 67 | \setsansfont[ItalicFont={Fira Sans Light Italic OT},% 68 | BoldFont={Fira Sans OT},% 69 | BoldItalicFont={Fira Sans Italic OT}]% 70 | {Fira Sans Light OT}% 71 | }{% 72 | \PackageWarning{beamerthememetropolis}{% 73 | Could not find Fira Sans fonts% 74 | } 75 | } 76 | } 77 | \iffontsavailable{Fira Mono, Fira Mono Bold}{% 78 | \setmonofont[BoldFont={Fira Mono Medium}]{Fira Mono}% 79 | }{% 80 | \iffontsavailable{Fira Mono OT, Fira Mono Bold OT}{% 81 | \setmonofont[BoldFont={Fira Mono Medium OT}]{Fira Mono OT}% 82 | }{% 83 | \PackageWarning{beamerthememetropolis}{% 84 | Could not find Fira Mono fonts% 85 | } 86 | } 87 | } 88 | \AtBeginEnvironment{tabular}{% 89 | \addfontfeature{Numbers={Monospaced}}% 90 | } 91 | }{% 92 | \PackageWarning{beamerthememetropolis}{% 93 | You need to compile with XeLaTeX or LuaLaTeX to use the Fira fonts% 94 | } 95 | } 96 | \setbeamerfont{title}{size=\Large,% 97 | series=\bfseries} 98 | \setbeamerfont{author}{size=\small} 99 | \setbeamerfont{date}{size=\small} 100 | \setbeamerfont{section title}{size=\Large,% 101 | series=\bfseries} 102 | \setbeamerfont{block title}{size=\normalsize,% 103 | series=\bfseries} 104 | \setbeamerfont{block title alerted}{size=\normalsize,% 105 | series=\bfseries} 106 | \setbeamerfont*{subtitle}{size=\large} 107 | \setbeamerfont{frametitle}{size=\large,% 108 | series=\bfseries} 109 | \setbeamerfont{caption}{size=\small} 110 | \setbeamerfont{caption name}{series=\bfseries} 111 | \setbeamerfont{description item}{series=\bfseries} 112 | \setbeamerfont{page number in head/foot}{size=\scriptsize} 113 | \setbeamerfont{bibliography entry author}{size=\normalsize,% 114 | series=\normalfont} 115 | \setbeamerfont{bibliography entry title}{size=\normalsize,% 116 | series=\bfseries} 117 | \setbeamerfont{bibliography entry location}{size=\normalsize,% 118 | series=\normalfont} 119 | \setbeamerfont{bibliography entry note}{size=\small,% 120 | series=\normalfont} 121 | \setbeamerfont{standout}{size=\Large,% 122 | series=\bfseries} 123 | \pgfkeys{ 124 | /metropolis/font/titleformat title/.cd, 125 | .is choice, 126 | regular/.code={% 127 | \let\metropolis@titleformat\@empty% 128 | \setbeamerfont{title}{shape=\normalfont}% 129 | }, 130 | smallcaps/.code={% 131 | \let\metropolis@titleformat\@empty% 132 | \setbeamerfont{title}{shape=\scshape}% 133 | }, 134 | allsmallcaps/.code={% 135 | \let\metropolis@titleformat\lowercase% 136 | \setbeamerfont{title}{shape=\scshape}% 137 | \PackageWarning{beamerthememetropolis}{% 138 | Be aware that titleformat title=allsmallcaps can lead to problems% 139 | } 140 | }, 141 | allcaps/.code={% 142 | \let\metropolis@titleformat\uppercase% 143 | \setbeamerfont{title}{shape=\normalfont} 144 | \PackageWarning{beamerthememetropolis}{% 145 | Be aware that titleformat title=allcaps can lead to problems% 146 | } 147 | }, 148 | } 149 | \pgfkeys{ 150 | /metropolis/font/titleformat subtitle/.cd, 151 | .is choice, 152 | regular/.code={% 153 | \let\metropolis@subtitleformat\@empty% 154 | \setbeamerfont{subtitle}{shape=\normalfont}% 155 | }, 156 | smallcaps/.code={% 157 | \let\metropolis@subtitleformat\@empty% 158 | \setbeamerfont{subtitle}{shape=\scshape}% 159 | }, 160 | allsmallcaps/.code={% 161 | \let\metropolis@subtitleformat\lowercase% 162 | \setbeamerfont{subtitle}{shape=\scshape}% 163 | \PackageWarning{beamerthememetropolis}{% 164 | Be aware that titleformat subtitle=allsmallcaps can lead to problems% 165 | } 166 | }, 167 | allcaps/.code={% 168 | \let\metropolis@subtitleformat\uppercase% 169 | \setbeamerfont{subtitle}{shape=\normalfont}% 170 | \PackageWarning{beamerthememetropolis}{% 171 | Be aware that titleformat subtitle=allcaps can lead to problems% 172 | } 173 | }, 174 | } 175 | \pgfkeys{ 176 | /metropolis/font/titleformat section/.cd, 177 | .is choice, 178 | regular/.code={% 179 | \let\metropolis@sectiontitleformat\@empty% 180 | \setbeamerfont{section title}{shape=\normalfont}% 181 | }, 182 | smallcaps/.code={% 183 | \let\metropolis@sectiontitleformat\@empty% 184 | \setbeamerfont{section title}{shape=\scshape}% 185 | }, 186 | allsmallcaps/.code={% 187 | \let\metropolis@sectiontitleformat\MakeLowercase% 188 | \setbeamerfont{section title}{shape=\scshape}% 189 | \PackageWarning{beamerthememetropolis}{% 190 | Be aware that titleformat section=allsmallcaps can lead to problems% 191 | } 192 | }, 193 | allcaps/.code={% 194 | \let\metropolis@sectiontitleformat\MakeUppercase% 195 | \setbeamerfont{section title}{shape=\normalfont}% 196 | \PackageWarning{beamerthememetropolis}{% 197 | Be aware that titleformat section=allcaps can lead to problems% 198 | } 199 | }, 200 | } 201 | \pgfkeys{ 202 | /metropolis/font/titleformat frame/.cd, 203 | .is choice, 204 | regular/.code={% 205 | \let\metropolis@frametitleformat\@empty% 206 | \setbeamerfont{frametitle}{shape=\normalfont}% 207 | }, 208 | smallcaps/.code={% 209 | \let\metropolis@frametitleformat\@empty% 210 | \setbeamerfont{frametitle}{shape=\scshape}% 211 | }, 212 | allsmallcaps/.code={% 213 | \let\metropolis@frametitleformat\MakeLowercase% 214 | \setbeamerfont{frametitle}{shape=\scshape}% 215 | \PackageWarning{beamerthememetropolis}{% 216 | Be aware that titleformat frame=allsmallcaps can lead to problems% 217 | } 218 | }, 219 | allcaps/.code={% 220 | \let\metropolis@frametitleformat\MakeUppercase% 221 | \setbeamerfont{frametitle}{shape=\normalfont} 222 | \PackageWarning{beamerthememetropolis}{% 223 | Be aware that titleformat frame=allcaps can lead to problems% 224 | } 225 | }, 226 | } 227 | \pgfkeys{ 228 | /metropolis/font/.cd, 229 | titleformattitle/.code=\pgfkeysalso{titleformat title=#1}, 230 | titleformatsubtitle/.code=\pgfkeysalso{titleformat subtitle=#1}, 231 | titleformatsection/.code=\pgfkeysalso{titleformat section=#1}, 232 | titleformatframe/.code=\pgfkeysalso{titleformat frame=#1}, 233 | } 234 | \newcommand{\metropolis@font@setdefaults}{ 235 | \pgfkeys{/metropolis/font/.cd, 236 | titleformat title=regular, 237 | titleformat subtitle=regular, 238 | titleformat section=regular, 239 | titleformat frame=regular, 240 | } 241 | } 242 | \def\metropolis@titleformat#1{#1} 243 | \def\metropolis@subtitleformat#1{#1} 244 | \def\metropolis@sectiontitleformat#1{#1} 245 | \def\metropolis@frametitleformat#1{#1} 246 | \patchcmd{\beamer@title}% 247 | {\def\inserttitle{#2}}% 248 | {\def\inserttitle{\metropolis@titleformat{#2}}}% 249 | {}% 250 | {\PackageError{beamerfontthememetropolis}{Patching title failed}\@ehc} 251 | \patchcmd{\beamer@subtitle}% 252 | {\def\insertsubtitle{#2}}% 253 | {\def\insertsubtitle{\metropolis@subtitleformat{#2}}}% 254 | {}% 255 | {\PackageError{beamerfontthememetropolis}{Patching subtitle failed}\@ehc} 256 | \patchcmd{\sectionentry} 257 | {\def\insertsectionhead{#2}} 258 | {\def\insertsectionhead{\metropolis@sectiontitleformat{#2}}} 259 | {} 260 | {\PackageError{beamerfontthememetropolis}{Patching section title failed}\@ehc} 261 | \@tempswafalse 262 | \patchcmd{\beamer@section} 263 | {\edef\insertsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{\unexpanded{#1}}}} 264 | {\edef\insertsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{% 265 | \noexpand\metropolis@sectiontitleformat{\unexpanded{#1}}}}} 266 | {\@tempswatrue} 267 | {} 268 | \patchcmd{\beamer@section} 269 | {\def\insertsectionhead{\hyperlink{Navigation\the\c@page}{#1}}} 270 | {\def\insertsectionhead{\hyperlink{Navigation\the\c@page}{% 271 | \metropolis@sectiontitleformat{#1}}}} 272 | {\@tempswatrue} 273 | {} 274 | \patchcmd{\beamer@section} 275 | {\protected@edef\insertsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{#1}}} 276 | {\protected@edef\insertsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{% 277 | \noexpand\metropolis@sectiontitleformat{#1}}}} 278 | {\@tempswatrue} 279 | {} 280 | \if@tempswa\else 281 | \PackageError{beamerfontthememetropolis}{Patching section title failed}\@ehc 282 | \fi 283 | \@tempswafalse 284 | \patchcmd{\beamer@subsection} 285 | {\edef\insertsubsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{\unexpanded{#1}}}} 286 | {\edef\insertsubsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{% 287 | \noexpand\metropolis@sectiontitleformat{\unexpanded{#1}}}}} 288 | {\@tempswatrue} 289 | {} 290 | \patchcmd{\beamer@subsection} 291 | {\def\insertsubsectionhead{\hyperlink{Navigation\the\c@page}{#1}}} 292 | {\def\insertsubsectionhead{\hyperlink{Navigation\the\c@page}{% 293 | \metropolis@sectiontitleformat{#1}}}} 294 | {\@tempswatrue} 295 | {} 296 | \patchcmd{\beamer@subsection} 297 | {\protected@edef\insertsubsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{#1}}} 298 | {\protected@edef\insertsubsectionhead{\noexpand\hyperlink{Navigation\the\c@page}{% 299 | \noexpand\metropolis@sectiontitleformat{#1}}}} 300 | {\@tempswatrue} 301 | {} 302 | \if@tempswa\else 303 | \PackageError{beamerfontthememetropolis}{Patching section title failed}\@ehc 304 | \fi 305 | \patchcmd{\beamer@@frametitle} 306 | {{% 307 | \gdef\insertframetitle{{#2\ifnum\beamer@autobreakcount>0\relax{}\space% 308 | \usebeamertemplate*{frametitle continuation}\fi}}% 309 | \gdef\beamer@frametitle{#2}% 310 | \gdef\beamer@shortframetitle{#1}% 311 | }} 312 | {{% 313 | \gdef\insertframetitle{{\metropolis@frametitleformat{#2}\ifnum% 314 | \beamer@autobreakcount>0\relax{}\space% 315 | \usebeamertemplate*{frametitle continuation}\fi}}% 316 | \gdef\beamer@frametitle{#2}% 317 | \gdef\beamer@shortframetitle{#1}% 318 | }} 319 | {} 320 | {\PackageError{beamerfontthememetropolis}{Patching frame title failed}\@ehc} 321 | \metropolis@font@setdefaults 322 | \ProcessPgfPackageOptions{/metropolis/font} 323 | \endinput 324 | %% 325 | %% End of file `beamerfontthememetropolis.sty'. 326 | -------------------------------------------------------------------------------- /talk/beamerinnerthememetropolis.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `beamerinnerthememetropolis.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% beamerinnerthememetropolis.dtx (with options: `package') 8 | %% --------------------------------------------------------------------------- 9 | %% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of 10 | %% contributors can be found at 11 | %% 12 | %% https://github.com/matze/mtheme/graphs/contributors 13 | %% 14 | %% and the original template was based on the HSRM theme by Benjamin Weiss. 15 | %% 16 | %% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 17 | %% International License (https://creativecommons.org/licenses/by-sa/4.0/). 18 | %% --------------------------------------------------------------------------- 19 | \NeedsTeXFormat{LaTeX2e} 20 | \ProvidesPackage{beamerinnerthememetropolis}[2017/01/23 Metropolis inner theme] 21 | \RequirePackage{etoolbox} 22 | \RequirePackage{keyval} 23 | \RequirePackage{calc} 24 | \RequirePackage{pgfopts} 25 | \RequirePackage{tikz} 26 | \pgfkeys{ 27 | /metropolis/inner/sectionpage/.cd, 28 | .is choice, 29 | none/.code=\metropolis@disablesectionpage, 30 | simple/.code={\metropolis@enablesectionpage 31 | \setbeamertemplate{section page}[simple]}, 32 | progressbar/.code={\metropolis@enablesectionpage 33 | \setbeamertemplate{section page}[progressbar]}, 34 | } 35 | \pgfkeys{ 36 | /metropolis/inner/subsectionpage/.cd, 37 | .is choice, 38 | none/.code=\metropolis@disablesubsectionpage, 39 | simple/.code={\metropolis@enablesubsectionpage 40 | \setbeamertemplate{section page}[simple]}, 41 | progressbar/.code={\metropolis@enablesubsectionpage 42 | \setbeamertemplate{section page}[progressbar]}, 43 | } 44 | \newcommand{\metropolis@inner@setdefaults}{ 45 | \pgfkeys{/metropolis/inner/.cd, 46 | sectionpage=progressbar, 47 | subsectionpage=none 48 | } 49 | } 50 | \setbeamertemplate{title page}{ 51 | \begin{minipage}[b][\paperheight]{\textwidth} 52 | \ifx\inserttitlegraphic\@empty\else\usebeamertemplate*{title graphic}\fi 53 | \vfill% 54 | \ifx\inserttitle\@empty\else\usebeamertemplate*{title}\fi 55 | \ifx\insertsubtitle\@empty\else\usebeamertemplate*{subtitle}\fi 56 | \usebeamertemplate*{title separator} 57 | \ifx\beamer@shortauthor\@empty\else\usebeamertemplate*{author}\fi 58 | \ifx\insertdate\@empty\else\usebeamertemplate*{date}\fi 59 | \ifx\insertinstitute\@empty\else\usebeamertemplate*{institute}\fi 60 | \vfill 61 | \vspace*{1mm} 62 | \end{minipage} 63 | } 64 | \def\maketitle{% 65 | \ifbeamer@inframe 66 | \titlepage 67 | \else 68 | \frame[plain,noframenumbering]{\titlepage} 69 | \fi 70 | } 71 | \def\titlepage{% 72 | \usebeamertemplate{title page} 73 | } 74 | \setbeamertemplate{title graphic}{ 75 | \vbox to 0pt { 76 | \vspace*{2em} 77 | \inserttitlegraphic% 78 | }% 79 | \nointerlineskip% 80 | } 81 | \setbeamertemplate{title}{ 82 | \raggedright% 83 | \linespread{1.0}% 84 | \inserttitle% 85 | \par% 86 | \vspace*{0.5em} 87 | } 88 | \setbeamertemplate{subtitle}{ 89 | \raggedright% 90 | \insertsubtitle% 91 | \par% 92 | \vspace*{0.5em} 93 | } 94 | \newlength{\metropolis@titleseparator@linewidth} 95 | \setlength{\metropolis@titleseparator@linewidth}{0.4pt} 96 | \setbeamertemplate{title separator}{ 97 | \tikzexternaldisable% 98 | \begin{tikzpicture} 99 | \fill[fg] (0,0) rectangle (\textwidth, \metropolis@titleseparator@linewidth); 100 | \end{tikzpicture}% 101 | \tikzexternalenable% 102 | \par% 103 | } 104 | \setbeamertemplate{author}{ 105 | \vspace*{2em} 106 | \insertauthor% 107 | \par% 108 | \vspace*{0.25em} 109 | } 110 | \setbeamertemplate{date}{ 111 | \insertdate% 112 | \par% 113 | } 114 | \setbeamertemplate{institute}{ 115 | \vspace*{3mm} 116 | \insertinstitute% 117 | \par% 118 | } 119 | \defbeamertemplate{section page}{simple}{ 120 | \begin{center} 121 | \usebeamercolor[fg]{section title} 122 | \usebeamerfont{section title} 123 | \insertsectionhead\par 124 | \ifx\insertsubsectionhead\@empty\else 125 | \usebeamercolor[fg]{subsection title} 126 | \usebeamerfont{subsection title} 127 | \insertsubsectionhead 128 | \fi 129 | \end{center} 130 | } 131 | \defbeamertemplate{section page}{progressbar}{ 132 | \centering 133 | \begin{minipage}{22em} 134 | \raggedright 135 | \usebeamercolor[fg]{section title} 136 | \usebeamerfont{section title} 137 | \insertsectionhead\\[-1ex] 138 | \usebeamertemplate*{progress bar in section page} 139 | \par 140 | \ifx\insertsubsectionhead\@empty\else% 141 | \usebeamercolor[fg]{subsection title}% 142 | \usebeamerfont{subsection title}% 143 | \insertsubsectionhead 144 | \fi 145 | \end{minipage} 146 | \par 147 | \vspace{\baselineskip} 148 | } 149 | \newcommand{\metropolis@disablesectionpage}{ 150 | \AtBeginSection{ 151 | % intentionally empty 152 | } 153 | } 154 | \newcommand{\metropolis@enablesectionpage}{ 155 | \AtBeginSection{ 156 | \ifbeamer@inframe 157 | \sectionpage 158 | \else 159 | \frame[plain,c,noframenumbering]{\sectionpage} 160 | \fi 161 | } 162 | } 163 | \setbeamertemplate{subsection page}{% 164 | \usebeamertemplate*{section page} 165 | } 166 | \newcommand{\metropolis@disablesubsectionpage}{ 167 | \AtBeginSubsection{ 168 | % intentionally empty 169 | } 170 | } 171 | \newcommand{\metropolis@enablesubsectionpage}{ 172 | \AtBeginSubsection{ 173 | \ifbeamer@inframe 174 | \subsectionpage 175 | \else 176 | \frame[plain,c,noframenumbering]{\subsectionpage} 177 | \fi 178 | } 179 | } 180 | \newlength{\metropolis@progressonsectionpage} 181 | \newlength{\metropolis@progressonsectionpage@linewidth} 182 | \setlength{\metropolis@progressonsectionpage@linewidth}{0.4pt} 183 | \setbeamertemplate{progress bar in section page}{ 184 | \setlength{\metropolis@progressonsectionpage}{% 185 | \textwidth * \ratio{\insertframenumber pt}{\inserttotalframenumber pt}% 186 | }% 187 | \tikzexternaldisable% 188 | \begin{tikzpicture} 189 | \fill[bg] (0,0) rectangle (\textwidth, \metropolis@progressonsectionpage@linewidth); 190 | \fill[fg] (0,0) rectangle (\metropolis@progressonsectionpage, \metropolis@progressonsectionpage@linewidth); 191 | \end{tikzpicture}% 192 | \tikzexternalenable% 193 | } 194 | \def\inserttotalframenumber{100} 195 | \newlength{\metropolis@blocksep} 196 | \newlength{\metropolis@blockadjust} 197 | \setlength{\metropolis@blocksep}{0.75ex} 198 | \setlength{\metropolis@blockadjust}{0.25ex} 199 | \providecommand{\metropolis@strut}{% 200 | \vphantom{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz()}% 201 | } 202 | \newcommand{\metropolis@block}[1]{ 203 | \par\vskip\medskipamount% 204 | \setlength{\parskip}{0pt} 205 | \ifbeamercolorempty[bg]{block title#1}{% 206 | \begin{beamercolorbox}[rightskip=0pt plus 4em]{block title#1}}{% 207 | \ifbeamercolorempty[bg]{block title}{% 208 | \begin{beamercolorbox}[rightskip=0pt plus 4em]{block title#1}% 209 | }% 210 | {% 211 | \begin{beamercolorbox}[ 212 | sep=\dimexpr\metropolis@blocksep-\metropolis@blockadjust\relax, 213 | leftskip=\metropolis@blockadjust, 214 | rightskip=\dimexpr\metropolis@blockadjust plus 4em\relax 215 | ]{block title#1}% 216 | }}% 217 | \usebeamerfont*{block title#1}% 218 | \metropolis@strut% 219 | \insertblocktitle% 220 | \metropolis@strut% 221 | \end{beamercolorbox}% 222 | \nointerlineskip% 223 | \ifbeamercolorempty[bg]{block body#1}{% 224 | \begin{beamercolorbox}[vmode]{block body#1}}{ 225 | \ifbeamercolorempty[bg]{block body}{% 226 | \begin{beamercolorbox}[vmode]{block body#1}% 227 | }{% 228 | \begin{beamercolorbox}[sep=\metropolis@blocksep, vmode]{block body#1}% 229 | \vspace{-\metropolis@parskip} 230 | }}% 231 | \usebeamerfont{block body#1}% 232 | \setlength{\parskip}{\metropolis@parskip}% 233 | } 234 | \setbeamertemplate{block begin}{\metropolis@block{}} 235 | \setbeamertemplate{block alerted begin}{\metropolis@block{ alerted}} 236 | \setbeamertemplate{block example begin}{\metropolis@block{ example}} 237 | \setbeamertemplate{block end}{\end{beamercolorbox}\vspace*{0.2ex}} 238 | \setbeamertemplate{block alerted end}{\end{beamercolorbox}\vspace*{0.2ex}} 239 | \setbeamertemplate{block example end}{\end{beamercolorbox}\vspace*{0.2ex}} 240 | \setbeamertemplate{itemize items}{\textbullet} 241 | \setbeamertemplate{caption label separator}{: } 242 | \setbeamertemplate{caption}[numbered] 243 | \setbeamertemplate{footnote}{% 244 | \parindent 0em\noindent% 245 | \raggedright 246 | \usebeamercolor{footnote}\hbox to 0.8em{\hfil\insertfootnotemark}\insertfootnotetext\par% 247 | } 248 | \newlength{\metropolis@parskip} 249 | \setlength{\metropolis@parskip}{0.5em} 250 | \setlength{\parskip}{\metropolis@parskip} 251 | \linespread{1.15} 252 | \define@key{beamerframe}{c}[true]{% centered 253 | \beamer@frametopskip=0pt plus 1fill\relax% 254 | \beamer@framebottomskip=0pt plus 1fill\relax% 255 | \beamer@frametopskipautobreak=0pt plus .4\paperheight\relax% 256 | \beamer@framebottomskipautobreak=0pt plus .6\paperheight\relax% 257 | \def\beamer@initfirstlineunskip{}% 258 | } 259 | \providebool{metropolis@standout} 260 | \define@key{beamerframe}{standout}[true]{% 261 | \booltrue{metropolis@standout} 262 | \begingroup 263 | \setkeys{beamerframe}{c} 264 | \setkeys{beamerframe}{noframenumbering} 265 | \ifbeamercolorempty[bg]{palette primary}{ 266 | \setbeamercolor{background canvas}{ 267 | use=palette primary, 268 | bg=-palette primary.fg 269 | } 270 | }{ 271 | \setbeamercolor{background canvas}{ 272 | use=palette primary, 273 | bg=palette primary.bg 274 | } 275 | } 276 | \setbeamercolor{local structure}{ 277 | fg=palette primary.fg 278 | } 279 | \centering 280 | \usebeamercolor[fg]{palette primary} 281 | \usebeamerfont{standout} 282 | } 283 | \apptocmd{\beamer@reseteecodes}{% 284 | \ifbool{metropolis@standout}{ 285 | \endgroup 286 | \boolfalse{metropolis@standout} 287 | }{} 288 | }{}{} 289 | \metropolis@inner@setdefaults 290 | \ProcessPgfPackageOptions{/metropolis/inner} 291 | \endinput 292 | %% 293 | %% End of file `beamerinnerthememetropolis.sty'. 294 | -------------------------------------------------------------------------------- /talk/beamerouterthememetropolis.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `beamerouterthememetropolis.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% beamerouterthememetropolis.dtx (with options: `package') 8 | %% --------------------------------------------------------------------------- 9 | %% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of 10 | %% contributors can be found at 11 | %% 12 | %% https://github.com/matze/mtheme/graphs/contributors 13 | %% 14 | %% and the original template was based on the HSRM theme by Benjamin Weiss. 15 | %% 16 | %% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 17 | %% International License (https://creativecommons.org/licenses/by-sa/4.0/). 18 | %% --------------------------------------------------------------------------- 19 | \NeedsTeXFormat{LaTeX2e} 20 | \ProvidesPackage{beamerouterthememetropolis}[2017/01/23 Metropolis outer theme] 21 | \RequirePackage{etoolbox} 22 | \RequirePackage{calc} 23 | \RequirePackage{pgfopts} 24 | \pgfkeys{ 25 | /metropolis/outer/numbering/.cd, 26 | .is choice, 27 | none/.code=\setbeamertemplate{frame numbering}[none], 28 | counter/.code=\setbeamertemplate{frame numbering}[counter], 29 | fraction/.code=\setbeamertemplate{frame numbering}[fraction], 30 | } 31 | \pgfkeys{ 32 | /metropolis/outer/progressbar/.cd, 33 | .is choice, 34 | none/.code={% 35 | \setbeamertemplate{headline}[plain] 36 | \setbeamertemplate{frametitle}[plain] 37 | \setbeamertemplate{footline}[plain] 38 | }, 39 | head/.code={\pgfkeys{/metropolis/outer/progressbar=none} 40 | \addtobeamertemplate{headline}{}{% 41 | \usebeamertemplate*{progress bar in head/foot} 42 | } 43 | }, 44 | frametitle/.code={\pgfkeys{/metropolis/outer/progressbar=none} 45 | \addtobeamertemplate{frametitle}{}{% 46 | \usebeamertemplate*{progress bar in head/foot} 47 | } 48 | }, 49 | foot/.code={\pgfkeys{/metropolis/outer/progressbar=none} 50 | \addtobeamertemplate{footline}{}{% 51 | \usebeamertemplate*{progress bar in head/foot}% 52 | } 53 | }, 54 | } 55 | \newcommand{\metropolis@outer@setdefaults}{ 56 | \pgfkeys{/metropolis/outer/.cd, 57 | numbering=counter, 58 | progressbar=none, 59 | } 60 | } 61 | \setbeamertemplate{navigation symbols}{} 62 | \defbeamertemplate{frame footer}{none}{} 63 | \defbeamertemplate{frame footer}{custom}[1]{ #1 } 64 | \defbeamertemplate{frame numbering}{none}{} 65 | \defbeamertemplate{frame numbering}{counter}{\insertframenumber} 66 | \defbeamertemplate{frame numbering}{fraction}{ 67 | \insertframenumber/\inserttotalframenumber 68 | } 69 | \defbeamertemplate{headline}{plain}{} 70 | \defbeamertemplate{footline}{plain}{% 71 | \begin{beamercolorbox}[wd=\textwidth, sep=3ex]{footline}% 72 | \usebeamerfont{page number in head/foot}% 73 | \usebeamertemplate*{frame footer} 74 | \hfill% 75 | \usebeamertemplate*{frame numbering} 76 | \end{beamercolorbox}% 77 | } 78 | \newlength{\metropolis@frametitle@padding} 79 | \setlength{\metropolis@frametitle@padding}{2.2ex} 80 | \newcommand{\metropolis@frametitlestrut@start}{ 81 | \rule{0pt}{\metropolis@frametitle@padding +% 82 | \totalheightof{% 83 | \ifcsdef{metropolis@frametitleformat}{\metropolis@frametitleformat X}{X}% 84 | }% 85 | }% 86 | } 87 | \newcommand{\metropolis@frametitlestrut@end}{ 88 | \rule[-\metropolis@frametitle@padding]{0pt}{\metropolis@frametitle@padding} 89 | } 90 | \defbeamertemplate{frametitle}{plain}{% 91 | \nointerlineskip% 92 | \begin{beamercolorbox}[% 93 | wd=\paperwidth,% 94 | sep=0pt,% 95 | leftskip=\metropolis@frametitle@padding,% 96 | rightskip=\metropolis@frametitle@padding,% 97 | ]{frametitle}% 98 | \metropolis@frametitlestrut@start% 99 | \insertframetitle% 100 | \nolinebreak% 101 | \metropolis@frametitlestrut@end% 102 | \end{beamercolorbox}% 103 | } 104 | \setbeamertemplate{frametitle continuation}{% 105 | \usebeamerfont{frametitle} 106 | \romannumeral \insertcontinuationcount 107 | } 108 | \newlength{\metropolis@progressinheadfoot} 109 | \newlength{\metropolis@progressinheadfoot@linewidth} 110 | \setlength{\metropolis@progressinheadfoot@linewidth}{0.4pt} 111 | \setbeamertemplate{progress bar in head/foot}{ 112 | \nointerlineskip 113 | \setlength{\metropolis@progressinheadfoot}{% 114 | \paperwidth * \ratio{\insertframenumber pt}{\inserttotalframenumber pt}% 115 | }% 116 | \begin{beamercolorbox}[wd=\paperwidth]{progress bar in head/foot} 117 | \tikzexternaldisable% 118 | \begin{tikzpicture} 119 | \fill[bg] (0,0) rectangle (\paperwidth, \metropolis@progressinheadfoot@linewidth); 120 | \fill[fg] (0,0) rectangle (\metropolis@progressinheadfoot, \metropolis@progressinheadfoot@linewidth); 121 | \end{tikzpicture}% 122 | \tikzexternalenable% 123 | \end{beamercolorbox} 124 | } 125 | \AtBeginDocument{% 126 | \apptocmd{\appendix}{% 127 | \pgfkeys{% 128 | /metropolis/outer/.cd, 129 | numbering=none, 130 | progressbar=none} 131 | }{}{} 132 | } 133 | \metropolis@outer@setdefaults 134 | \ProcessPgfPackageOptions{/metropolis/outer} 135 | \endinput 136 | %% 137 | %% End of file `beamerouterthememetropolis.sty'. 138 | -------------------------------------------------------------------------------- /talk/beamerthememetropolis.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `beamerthememetropolis.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% beamerthememetropolis.dtx (with options: `package') 8 | %% --------------------------------------------------------------------------- 9 | %% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of 10 | %% contributors can be found at 11 | %% 12 | %% https://github.com/matze/mtheme/graphs/contributors 13 | %% 14 | %% and the original template was based on the HSRM theme by Benjamin Weiss. 15 | %% 16 | %% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 17 | %% International License (https://creativecommons.org/licenses/by-sa/4.0/). 18 | %% --------------------------------------------------------------------------- 19 | \NeedsTeXFormat{LaTeX2e} 20 | \ProvidesPackage{beamerthememetropolis} 21 | [2017/01/23 v1.2 Metropolis Beamer theme] 22 | \RequirePackage{etoolbox} 23 | \RequirePackage{pgfopts} 24 | \pgfkeys{/metropolis/.cd, 25 | .search also={ 26 | /metropolis/inner, 27 | /metropolis/outer, 28 | /metropolis/color, 29 | /metropolis/font, 30 | } 31 | } 32 | \pgfkeys{ 33 | /metropolis/titleformat plain/.cd, 34 | .is choice, 35 | regular/.code={% 36 | \let\metropolis@plaintitleformat\@empty% 37 | \setbeamerfont{standout}{shape=\normalfont}% 38 | }, 39 | smallcaps/.code={% 40 | \let\metropolis@plaintitleformat\@empty% 41 | \setbeamerfont{standout}{shape=\scshape}% 42 | }, 43 | allsmallcaps/.code={% 44 | \let\metropolis@plaintitleformat\MakeLowercase% 45 | \setbeamerfont{standout}{shape=\scshape}% 46 | \PackageWarning{beamerthememetropolis}{% 47 | Be aware that titleformat plain=allsmallcaps can lead to problems% 48 | } 49 | }, 50 | allcaps/.code={% 51 | \let\metropolis@plaintitleformat\MakeUppercase% 52 | \setbeamerfont{standout}{shape=\normalfont}% 53 | \PackageWarning{beamerthememetropolis}{% 54 | Be aware that titleformat plain=allcaps can lead to problems% 55 | } 56 | }, 57 | } 58 | \pgfkeys{ 59 | /metropolis/titleformat/.code=\pgfkeysalso{ 60 | font/titleformat title=#1, 61 | font/titleformat subtitle=#1, 62 | font/titleformat section=#1, 63 | font/titleformat frame=#1, 64 | titleformat plain=#1, 65 | } 66 | } 67 | \pgfkeys{/metropolis/.cd, 68 | usetitleprogressbar/.code=\pgfkeysalso{outer/progressbar=frametitle}, 69 | noslidenumbers/.code=\pgfkeysalso{outer/numbering=none}, 70 | usetotalslideindicator/.code=\pgfkeysalso{outer/numbering=fraction}, 71 | nosectionslide/.code=\pgfkeysalso{inner/sectionpage=none}, 72 | darkcolors/.code=\pgfkeysalso{color/background=dark}, 73 | blockbg/.code=\pgfkeysalso{color/block=fill, inner/block=fill}, 74 | } 75 | \newcommand{\metropolis@setdefaults}{ 76 | \pgfkeys{/metropolis/.cd, 77 | titleformat plain=regular, 78 | } 79 | } 80 | \providecommand{\tikzexternalenable}{} 81 | \providecommand{\tikzexternaldisable}{} 82 | \useinnertheme{metropolis} 83 | \useoutertheme{metropolis} 84 | \usecolortheme{metropolis} 85 | \usefonttheme{metropolis} 86 | \AtEndPreamble{% 87 | \@ifpackageloaded{pgfplots}{% 88 | \RequirePackage{pgfplotsthemetol} 89 | }{} 90 | } 91 | \newcommand{\metroset}[1]{\pgfkeys{/metropolis/.cd,#1}} 92 | \def\metropolis@plaintitleformat#1{#1} 93 | \newcommand{\plain}[2][]{% 94 | \PackageWarning{beamerthememetropolis}{% 95 | The syntax `\plain' may be deprecated in a future version of Metropolis. 96 | Please use a frame with [standout] instead. 97 | } 98 | \begin{frame}[standout]{#1} 99 | \metropolis@plaintitleformat{#2} 100 | \end{frame} 101 | } 102 | \newcommand{\mreducelistspacing}{\vspace{-\topsep}} 103 | \metropolis@setdefaults 104 | \ProcessPgfOptions{/metropolis} 105 | \endinput 106 | %% 107 | %% End of file `beamerthememetropolis.sty'. 108 | -------------------------------------------------------------------------------- /talk/figures/punch_card_stack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levex/debugger-talk/e7b5ed8230362aec7dae2ad37b7f5b7eb01fea07/talk/figures/punch_card_stack.jpg -------------------------------------------------------------------------------- /talk/figures/tx0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levex/debugger-talk/e7b5ed8230362aec7dae2ad37b7f5b7eb01fea07/talk/figures/tx0.jpg -------------------------------------------------------------------------------- /talk/pgfplotsthemetol.sty: -------------------------------------------------------------------------------- 1 | %% 2 | %% This is file `pgfplotsthemetol.sty', 3 | %% generated with the docstrip utility. 4 | %% 5 | %% The original source files were: 6 | %% 7 | %% pgfplotsthemetol.dtx (with options: `package') 8 | %% --------------------------------------------------------------------------- 9 | %% Copyright 2015 Matthias Vogelgesang and the LaTeX community. A full list of 10 | %% contributors can be found at 11 | %% 12 | %% https://github.com/matze/mtheme/graphs/contributors 13 | %% 14 | %% and the original template was based on the HSRM theme by Benjamin Weiss. 15 | %% 16 | %% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 17 | %% International License (https://creativecommons.org/licenses/by-sa/4.0/). 18 | %% --------------------------------------------------------------------------- 19 | \NeedsTeXFormat{LaTeX2e} 20 | \ProvidesPackage{pgfplotsthemetol} 21 | [2017/01/23 PGFplots colors based on Paul Tol's SRON technical note] 22 | \definecolor{TolDarkPurple}{HTML}{332288} 23 | \definecolor{TolDarkBlue}{HTML}{6699CC} 24 | \definecolor{TolLightBlue}{HTML}{88CCEE} 25 | \definecolor{TolLightGreen}{HTML}{44AA99} 26 | \definecolor{TolDarkGreen}{HTML}{117733} 27 | \definecolor{TolDarkBrown}{HTML}{999933} 28 | \definecolor{TolLightBrown}{HTML}{DDCC77} 29 | \definecolor{TolDarkRed}{HTML}{661100} 30 | \definecolor{TolLightRed}{HTML}{CC6677} 31 | \definecolor{TolLightPink}{HTML}{AA4466} 32 | \definecolor{TolDarkPink}{HTML}{882255} 33 | \definecolor{TolLightPurple}{HTML}{AA4499} 34 | \pgfplotscreateplotcyclelist{mbarplot cycle}{% 35 | {draw=TolDarkBlue, fill=TolDarkBlue!70}, 36 | {draw=TolLightBrown, fill=TolLightBrown!70}, 37 | {draw=TolLightGreen, fill=TolLightGreen!70}, 38 | {draw=TolDarkPink, fill=TolDarkPink!70}, 39 | {draw=TolDarkPurple, fill=TolDarkPurple!70}, 40 | {draw=TolDarkRed, fill=TolDarkRed!70}, 41 | {draw=TolDarkBrown, fill=TolDarkBrown!70}, 42 | {draw=TolLightRed, fill=TolLightRed!70}, 43 | {draw=TolLightPink, fill=TolLightPink!70}, 44 | {draw=TolLightPurple, fill=TolLightPurple!70}, 45 | {draw=TolLightBlue, fill=TolLightBlue!70}, 46 | {draw=TolDarkGreen, fill=TolDarkGreen!70}, 47 | } 48 | \pgfplotscreateplotcyclelist{mlineplot cycle}{% 49 | {TolDarkBlue, mark=*, mark size=1.5pt}, 50 | {TolLightBrown, mark=square*, mark size=1.3pt}, 51 | {TolLightGreen, mark=triangle*, mark size=1.5pt}, 52 | {TolDarkBrown, mark=diamond*, mark size=1.5pt}, 53 | } 54 | \pgfplotsset{ 55 | compat=1.9, 56 | mlineplot/.style={ 57 | mbaseplot, 58 | xmajorgrids=true, 59 | ymajorgrids=true, 60 | major grid style={dotted}, 61 | axis x line=bottom, 62 | axis y line=left, 63 | legend style={ 64 | cells={anchor=west}, 65 | draw=none 66 | }, 67 | cycle list name=mlineplot cycle, 68 | }, 69 | mbarplot base/.style={ 70 | mbaseplot, 71 | bar width=6pt, 72 | axis y line*=none, 73 | }, 74 | mbarplot/.style={ 75 | mbarplot base, 76 | ybar, 77 | xmajorgrids=false, 78 | ymajorgrids=true, 79 | area legend, 80 | legend image code/.code={% 81 | \draw[#1] (0cm,-0.1cm) rectangle (0.15cm,0.1cm); 82 | }, 83 | cycle list name=mbarplot cycle, 84 | }, 85 | horizontal mbarplot/.style={ 86 | mbarplot base, 87 | xmajorgrids=true, 88 | ymajorgrids=false, 89 | xbar stacked, 90 | area legend, 91 | legend image code/.code={% 92 | \draw[#1] (0cm,-0.1cm) rectangle (0.15cm,0.1cm); 93 | }, 94 | cycle list name=mbarplot cycle, 95 | }, 96 | mbaseplot/.style={ 97 | legend style={ 98 | draw=none, 99 | fill=none, 100 | cells={anchor=west}, 101 | }, 102 | x tick label style={ 103 | font=\footnotesize 104 | }, 105 | y tick label style={ 106 | font=\footnotesize 107 | }, 108 | legend style={ 109 | font=\footnotesize 110 | }, 111 | major grid style={ 112 | dotted, 113 | }, 114 | axis x line*=bottom, 115 | }, 116 | disable thousands separator/.style={ 117 | /pgf/number format/.cd, 118 | 1000 sep={} 119 | }, 120 | } 121 | \endinput 122 | %% 123 | %% End of file `pgfplotsthemetol.sty'. 124 | -------------------------------------------------------------------------------- /talk/talk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levex/debugger-talk/e7b5ed8230362aec7dae2ad37b7f5b7eb01fea07/talk/talk.pdf -------------------------------------------------------------------------------- /talk/talk.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} % default... % 2 | %\documentclass[notes=only]{beamer} % notes only % 3 | \usetheme{metropolis} 4 | 5 | \usepackage{graphicx} 6 | \usepackage{hyperref} 7 | %\usepackage{listings} 8 | \usepackage{minted} 9 | 10 | \graphicspath{{figures/}} 11 | 12 | %\usepackage{fontspec} 13 | %\setsansfont{Ubuntu} 14 | %\setmonofont{Ubuntu Mono} 15 | 16 | %%%% some of my lkurusa-tools %%%% 17 | 18 | \newcommand*{\emailify}[1]{$<$#1$>$} 19 | \newcommand*{\myemail}{\emailify{levex@linux.com}} 20 | \newcommand*{\ptrace}{\texttt{ptrace}} 21 | \newcommand*{\ptraceman}{\texttt{ptrace(2)}} 22 | \newcommand*{\sig}[1]{\texttt{SIG#1}} 23 | \newcommand*{\sigsegv}[0]{\sig{SEGV}} 24 | \newcommand*{\sigtrap}[0]{\sig{TRAP}} 25 | \newcommand*{\sigill}[0]{\sig{ILL}} 26 | 27 | %%%%%%%% 28 | 29 | \title{Let's write a Debugger!} 30 | \author{Levente Kurusa \myemail} 31 | \date{Imperial College London} 32 | \institute{\texttt{linux.conf.au 2018}, Sydney, Australia \hfill January 25, 2018} 33 | 34 | \begin{document} 35 | \maketitle 36 | 37 | \begin{frame}{Who am I?} 38 | \begin{itemize} 39 | \item Final year undergraduate at Imperial College London 40 | \item Previously at Apple and Red Hat 41 | \item Mostly working on operating systems and low-level performance 42 | \item Writes in C, Haskell, Rust, Go. 43 | \end{itemize} 44 | \end{frame} 45 | 46 | \section{History of debuggers} 47 | 48 | \begin{frame}{Single user machines} 49 | 50 | \begin{columns} 51 | \column{0.5\textwidth} 52 | \begin{itemize} 53 | \item One of the first computers in the world 54 | \item Small application was loaded at the top of the memory 55 | \begin{itemize} 56 | \item single step 57 | \item examine registers 58 | \item read/write memory 59 | \end{itemize} 60 | \end{itemize} 61 | 62 | \column{0.5\textwidth} 63 | \metroset{block=fill} 64 | \begin{block}{TX-0 at MIT} 65 | \includegraphics[width=0.4\paperwidth]{tx0.jpg} 66 | \end{block} 67 | 68 | \end{columns} 69 | 70 | \note{ 71 | Prepunched cards with the code\\ 72 | Names like DDT and ODT 73 | } 74 | 75 | \end{frame} 76 | 77 | \begin{frame}{Batch processing machines} 78 | \includegraphics<1>[width=\textwidth]{punch_card_stack.jpg} 79 | %TODO: https://en.wikipedia.org/wiki/Punched_card#/media/File:Punched_card_program_deck.agr.jpg 80 | %TODO: Mention license at the end and attribute 81 | \pause 82 | Debugged by putting macro call in the punch card and generating: 83 | \begin{itemize} 84 | \item Snapshots \textit{(register dump)} 85 | \item Core dumps \textit{(contents of memory)} 86 | \end{itemize} 87 | 88 | \note<2>{ 89 | A different class of machines was also on the rise. \\ 90 | Submit a stack of punch cards and wait for the result at the end of the day 91 | } 92 | 93 | \end{frame} 94 | 95 | \begin{frame}[fragile] 96 | \frametitle{printf} 97 | 98 | Then came CTSS \textit{(Compatible Time-Sharing System)}, one of the first time-sharing operating 99 | systems! \par 100 | \vspace{.5cm} 101 | Debugging suddenly became interactive. 102 | 103 | \metroset{block=fill} 104 | \begin{block}{printf-debugging} 105 | \begin{minted}{c} 106 | *ptr = 1337; 107 | printf("Did we crash at line %d?\n", __LINE__); 108 | *((int *) 0) = 1337; 109 | printf("Did we crash at line %d?\n", __LINE__); 110 | \end{minted} 111 | \end{block} 112 | 113 | \end{frame} 114 | 115 | \begin{frame}{Unix-es} 116 | \begin{itemize} 117 | \item The first version of UNIX had a debugger called, \texttt{DB} 118 | \item GNU had \texttt{GDB} and \texttt{LLDB} 119 | \item For Plan 9, \texttt{ADB} was created 120 | \end{itemize} 121 | \vskip.5cm 122 | These debuggers should be familiar! 123 | \end{frame} 124 | 125 | \section{Tracing processes} 126 | 127 | \begin{frame}[fragile] 128 | \frametitle{ptrace} 129 | 130 | Most debuggers heavily rely on a system call known as \ptrace. 131 | \vskip1cm 132 | \metroset{block=fill} 133 | \begin{block}{The prototype of \ptraceman} 134 | \begin{minted}{c} 135 | #include 136 | 137 | long ptrace(enum __ptrace_request request, pid_t pid, 138 | void *addr, void *data); 139 | \end{minted} 140 | \end{block} 141 | \end{frame} 142 | 143 | \begin{frame}{Signals} 144 | \begin{center} 145 | \only<1->How does \mintinline{c}{int a = 3, b = 0, c = a / b} result in a \sig{FPE}? 146 | \end{center} 147 | \only<2->{\begin{enumerate} 148 | \item<2-> Division by zero is noticed by the CPU% \hfill (condition) 149 | \item<3-> The CPU raises a divide-by-zero error \texttt{(\#DE)}% \hfill (exception) 150 | \item<4-> A handler in the kernel is eventually called%\hfill (ISR) 151 | \item<5-> The kernel sends a \sig{FPE} to the offending process%\hfill (signal queueing) 152 | \item<6-> Your signal handler is called (or not if it is \sig{KILL})% \hfill (signal delivery) 153 | \end{enumerate} 154 | } 155 | \end{frame} 156 | 157 | \begin{frame}{Implementation} 158 | \begin{itemize}[<+- | alert@+>] 159 | \only<1->{ 160 | \item<1-> \alert<2,3>{Enable tracing} 161 | \only<3->{ 162 | \begin{itemize} 163 | \item \texttt{PTRACE\_TRACEME} 164 | \end{itemize} 165 | } 166 | \item<1-> \alert<4,5>{Run until system call} 167 | \only<5->{ 168 | \begin{itemize} 169 | \item \texttt{PTRACE\_SYSCALL} 170 | \item \texttt{PTRACE\_SYSEMU} 171 | \end{itemize} 172 | } 173 | \item<1-> \alert<6,7>{Monitoring registers} 174 | \only<7->{ 175 | \begin{itemize} 176 | \item \texttt{PTRACE\_PEEKUSER / PTRACE\_POKEUSER} 177 | \item \texttt{PTRACE\_GETREGS / PTRACE\_SETREGS} 178 | \end{itemize} 179 | } 180 | \item<1-> \alert<8,9>{Single stepping} 181 | \only<9->{ 182 | \begin{itemize} 183 | \item \texttt{PTRACE\_SINGLESTEP} 184 | \end{itemize} 185 | } 186 | \item<1-> \alert<10,11>{Memory manipulation} 187 | \only<11->{ 188 | \begin{itemize} 189 | \item \texttt{PTRACE\_PEEKTEXT / PTRACE\_POKETEXT} 190 | \item \texttt{PTRACE\_PEEKDATA / PTRACE\_POKEDATA} 191 | \end{itemize} 192 | } 193 | } 194 | \end{itemize} 195 | \end{frame} 196 | 197 | \section{Architectural support} 198 | 199 | \begin{frame}{Interrupting a process} 200 | 201 | \only<1->{ 202 | \begin{center} 203 | {\Large \texttt{PTRACE\_SINGLESTEP}} 204 | \end{center} 205 | } 206 | 207 | \only<2->{ 208 | \begin{itemize} 209 | \item<2->[] \only<2,3>{\texttt{\%EFLAGS}} 210 | \only<3>{\texttt{\hskip-.4em.TF}} 211 | \only<4->{Trap flag \hfill \textit{(Sometimes referred to as "Trace flag")}} 212 | \begin{itemize} 213 | \item<5-> After each instruction, trap into \texttt{\#DB} interrupt 214 | \item<5-> The kernel delivers a \sigtrap 215 | \item<5-> This fact is delivered via a wait-event to the debugger 216 | \end{itemize} 217 | \end{itemize} 218 | } 219 | 220 | \end{frame} 221 | 222 | \begin{frame}{Interrupting a process} 223 | 224 | \only<1->{ 225 | \begin{center} 226 | {\Large Breakpoints} 227 | \end{center} 228 | } 229 | 230 | \only<2->{ 231 | \begin{itemize} 232 | \item<2-> \mintinline{asm}{ud2} \hfill (machine code: \mintinline{c}{0x0F 0x0B}) 233 | \begin{itemize} 234 | \item Triggers \texttt{\#UD} \--- Undefined instruction exception 235 | \end{itemize} 236 | \item<3-> \mintinline{asm}{int $3} %$% <-- to fix tex studio highlighting lol 237 | \hfill (machine code: \mintinline{c}{0xCC}) 238 | \begin{itemize} 239 | \item Triggers \texttt{\#BP} \--- Breakpoint exception 240 | \end{itemize} 241 | \end{itemize} 242 | } 243 | 244 | \end{frame} 245 | 246 | \begin{frame}[<+- | textit@+>]{Breakpoint implementation} 247 | \begin{itemize} 248 | \item<1-> Replace with "\mintinline{asm}{int $3}" %$%hack to fix tex studio highlight 249 | \item<2-> Take note of the previous instruction 250 | \item<3-> When the breakpoint is hit, replace with the previous instruction 251 | \item<4-> Try executing the instruction again 252 | \end{itemize} 253 | \begin{itemize} 254 | \item<4->[] \textit{Nota bene:} 255 | \item<4-> Could have used "\mintinline{asm}{ud2}" 256 | \end{itemize} 257 | \end{frame} 258 | 259 | \begin{frame}{Debug registers} 260 | \begin{itemize} 261 | \item<1-> \texttt{DR0\hspace{1mm}-\hspace{1mm}DR3}: Linear addresses 262 | \item<2-> \texttt{DR6}: Debug control\\ 263 | Contains bitmasks for: 264 | \begin{itemize} 265 | \item 1, 2, 4 or 8 bytes monitored 266 | \item Break on read, write, execute, or read+write 267 | \end{itemize} 268 | \item<3-> \texttt{DR7}: Debug status \\ 269 | Bitmask showing which of \texttt{DR0-DR3} triggered the \texttt{\#DB} 270 | \item<4-> \small \texttt{DR4} \& \texttt{DR5}: Obsolete aliases to \texttt{DR6} \& \texttt{DR7} 271 | \end{itemize} 272 | \end{frame} 273 | 274 | \begin{frame}{Thanks!} 275 | \begin{center} 276 | Thank you for your attention! \par 277 | \end{center} 278 | 279 | Twitter: @iLevex \hfill Email: \myemail \\ 280 | GitHub: levex \hfill Website: \url{http://osdev.me/} 281 | 282 | \vspace{1cm} 283 | 284 | \begin{small} 285 | The \LaTeX\hskip1mm theme is available at \url{github.com/matze/mtheme} 286 | 287 | Both the theme and the talk are licensed under the 288 | \href{http://creativecommons.org/licenses/by-sa/4.0/}{CC-BY-SA 4.0 International license}. 289 | 290 | \end{small} 291 | 292 | \end{frame} 293 | 294 | \end{document} 295 | -------------------------------------------------------------------------------- /talk/talk_lca2018.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/levex/debugger-talk/e7b5ed8230362aec7dae2ad37b7f5b7eb01fea07/talk/talk_lca2018.pdf -------------------------------------------------------------------------------- /talk_dbg/Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "capstone" 3 | version = "0.2.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "capstone-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "capstone-sys" 11 | version = "0.6.0" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | 14 | [[package]] 15 | name = "libc" 16 | version = "0.2.34" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | 19 | [[package]] 20 | name = "talk_dbg" 21 | version = "0.1.0" 22 | dependencies = [ 23 | "capstone 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 24 | "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", 25 | ] 26 | 27 | [metadata] 28 | "checksum capstone 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baec16ad9e8a53db13c6fad761ba1348b00b5dbe381ba152cba39b767253a508" 29 | "checksum capstone-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d39c6f285e36142eaef829881a2e724c51f31d3b550741ec958e4ec3f87f6ee" 30 | "checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" 31 | -------------------------------------------------------------------------------- /talk_dbg/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "talk_dbg" 3 | version = "0.1.0" 4 | authors = ["Levente Kurusa "] 5 | 6 | [dependencies] 7 | libc = "0.2.34" 8 | capstone = "0.2.0" 9 | -------------------------------------------------------------------------------- /talk_dbg/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::io; 3 | use std::mem::transmute; 4 | mod ptrace; 5 | mod target; 6 | use target::*; 7 | use std::io::Write; 8 | extern crate libc; 9 | extern crate capstone; 10 | use capstone::*; 11 | use capstone::arch::*; 12 | 13 | fn usage(name: &String) { 14 | println!("talkDbg -- a simple debugger written at SCALE 16x"); 15 | println!(" ... and some beforehand"); 16 | println!(" Licensed under the MIT license"); 17 | println!(" Author: Levente Kurusa "); 18 | println!(""); 19 | println!("Usage: {} EXEC - runs EXEC and attaches to it", name); 20 | } 21 | 22 | fn disassemble_at(target_pid: i32, rip: u64) -> String { 23 | let mut instruction: [u8; 16] = [0x90; 16]; 24 | 25 | unsafe { 26 | let rawtop = libc::ptrace(libc::PTRACE_PEEKTEXT, target_pid, rip, 0); 27 | let top: [u8; 8] = transmute(rawtop.to_le()); 28 | 29 | let rawbot = libc::ptrace(libc::PTRACE_PEEKTEXT, target_pid, rip + 8, 0); 30 | let bot: [u8; 8] = transmute(rawbot.to_le()); 31 | 32 | instruction[0..8].copy_from_slice(&top); 33 | instruction[8..].copy_from_slice(&bot); 34 | } 35 | 36 | let cs = Capstone::new() 37 | .x86() 38 | .mode(arch::x86::ArchMode::Mode64) 39 | .syntax(arch::x86::ArchSyntax::Att) 40 | .detail(true) 41 | .build() 42 | .ok() 43 | .expect("Failed to construct capstone disassembler"); 44 | 45 | //println!("disassembling: {:?}", instruction); 46 | 47 | let insns = cs.disasm_count(&instruction, rip, 1).ok().expect("Unknown instruction"); 48 | return format!("{}", insns.iter().nth(0).expect("no instruction")); 49 | } 50 | 51 | fn print_short_state(prg: &mut TargetProgram) { 52 | let regs = prg.get_user_struct().regs; 53 | 54 | println!("{}", disassemble_at(prg.target_pid, regs.rip)); 55 | println!("RIP: 0x{:016x} RSP: 0x{:016x} RBP: 0x{:016x}", 56 | regs.rip, regs.rsp, regs.rbp); 57 | } 58 | 59 | fn input_loop(prg: &mut TargetProgram) { 60 | let mut last_input: String = String::new(); 61 | let mut should_prompt: bool = true; 62 | 63 | loop { 64 | let reader = io::stdin(); 65 | let mut input = String::new(); 66 | if should_prompt { 67 | print!("(talkDbg) "); 68 | std::io::stdout().flush().ok().expect("DBG: failed to flush stdout"); 69 | reader.read_line(&mut input).ok().expect("DBG: couldn't read from console"); 70 | } 71 | 72 | if input.trim().len() == 0 { 73 | input = last_input.clone(); 74 | } else { 75 | last_input = String::from(input.trim().clone()); 76 | } 77 | 78 | if input.trim() == "h" { 79 | println!("Welcome to talkDbg, below are the commands you can use:"); 80 | println!(""); 81 | println!("s - singlestep"); 82 | println!("y - run & wait until next syscall"); 83 | println!("r - dump registers"); 84 | println!("c - continue until next breakpoint"); 85 | println!("b $addr - set a breakpoint at $addr"); 86 | println!("lsb - list breakpoints"); 87 | println!("h - show this help"); 88 | println!("q - quit"); 89 | } else if input.trim() == "s" { 90 | prg.singlestep(); 91 | prg.wait(); 92 | 93 | print_short_state(prg); 94 | } else if input.trim() == "c" { 95 | prg.cont(); 96 | let status: libc::c_int = prg.wait() as libc::c_int; 97 | 98 | unsafe { 99 | if libc::WIFEXITED(status) { 100 | /* we don't support breakpoints, so this must mean it exited */ 101 | prg.state = ProgramState::Exited; 102 | break; 103 | } else if libc::WIFSTOPPED(status) { 104 | prg.handle_breakpoint(); 105 | print_short_state(prg); 106 | } else { 107 | panic!("Something odd happened"); 108 | } 109 | } 110 | } else if input.trim() == "r" { 111 | let regs = prg.get_user_struct().regs; 112 | 113 | println!("RAX: 0x{:016x} RBX: 0x{:016x} RCX: 0x{:016x} RDX: 0x{:016x}", 114 | regs.rax, regs.rbx, regs.rcx, regs.rdx); 115 | println!("R15: 0x{:016x} R14: 0x{:016x} R13: 0x{:016x} R12: 0x{:016x}", 116 | regs.r15, regs.r14, regs.r13, regs.r12); 117 | println!("R11: 0x{:016x} R10: 0x{:016x} R9: 0x{:016x} R8: 0x{:016x}", 118 | regs.r11, regs.r10, regs.r9, regs.r8); 119 | println!("RSP: 0x{:016x} RBP: 0x{:016x} RSI: 0x{:016x} RDI: 0x{:016x}", 120 | regs.rsp, regs.rbp, regs.rsi, regs.rdi); 121 | println!("RIP: 0x{:016x} CS: 0x{:04x} EFLAGS: 0x{:08x}", 122 | regs.rip, regs.cs, regs.eflags); 123 | println!("SS: 0x{:04x} DS: 0x{:04x} ES: 0x{:04x} FS: 0x{:04x} GS: 0x{:04x}", 124 | regs.ss, regs.ds, regs.es, regs.fs, regs.gs); 125 | } else if input.trim() == "y" { 126 | /* continue and wait for next syscall */ 127 | prg.continue_and_wait_until_next_syscall(); 128 | 129 | /* check if we are in entry or exit */ 130 | if (prg.flags & PRG_FLAG_IN_SYSCALL) == 0{ 131 | /* entering a system call... */ 132 | prg.flags |= PRG_FLAG_IN_SYSCALL; 133 | should_prompt = false; 134 | 135 | /* the child was blocked, time to read the syscall # */ 136 | let orig_eax = prg.read_user(libc::ORIG_RAX) 137 | .ok() 138 | .expect("DBG: FATAL: ptrace failed to read the RAX register"); 139 | 140 | print!("DBG: Target invoked system call {}", orig_eax); 141 | 142 | if orig_eax == -1 || orig_eax == 60 || orig_eax == 231 { 143 | println!(""); 144 | prg.state = ProgramState::Exited; 145 | break; 146 | } 147 | } else { 148 | /* exiting a syscall */ 149 | prg.flags &= !PRG_FLAG_IN_SYSCALL; 150 | 151 | /* read the result register */ 152 | let result = prg.read_user(libc::RAX) 153 | .ok() 154 | .expect("DBG: FATAL: ptrace failed to read the RAX register"); 155 | 156 | println!(" with result {}", result); 157 | should_prompt = true; 158 | } 159 | } else if input.trim().starts_with("b ") { 160 | let address: String = input.trim().chars().skip(4).collect(); 161 | let addr: u64 = u64::from_str_radix(&address, 16).unwrap(); 162 | 163 | prg.set_breakpoint(addr); 164 | println!("Breakpoint set at 0x{:016x}!", addr); 165 | } else if input.trim() == "lsb" { 166 | prg.list_breakpoints(); 167 | } else if input.trim() == "q" { 168 | prg.kill(); 169 | break; 170 | } 171 | } 172 | 173 | if prg.state == ProgramState::Exited { 174 | println!("DBG: Target has exited"); 175 | } 176 | } 177 | 178 | fn target_start(target: &String) { 179 | let target_pid: libc::pid_t; 180 | unsafe { 181 | target_pid = libc::fork(); 182 | } 183 | 184 | let mut prg: TargetProgram = TargetProgram::new(target_pid, target); 185 | 186 | /* FIXME: handle when the fork fails */ 187 | if target_pid == 0 { 188 | 189 | println!("TRG: running {}", target); 190 | prg.run(); 191 | 192 | return; 193 | } else { 194 | /* this is the debugger instance */ 195 | println!("DBG: debugger attaching to pid {}", target_pid); 196 | 197 | /* wait for the first stop... */ 198 | prg.wait(); 199 | 200 | /* then start the input loop */ 201 | input_loop(&mut prg); 202 | } 203 | } 204 | 205 | fn main() { 206 | let args: Vec = env::args().collect(); 207 | 208 | /* if there are no arguments then show usage & exit */ 209 | if args.len() < 2 { 210 | usage(&args[0]); 211 | return; 212 | } 213 | 214 | /* extract the target */ 215 | let target: &String = &args[1]; 216 | 217 | /* start the target */ 218 | target_start(target); 219 | } 220 | -------------------------------------------------------------------------------- /talk_dbg/src/ptrace/mod.rs: -------------------------------------------------------------------------------- 1 | use std; 2 | extern crate libc; 3 | 4 | pub fn trace_me() { 5 | unsafe { 6 | libc::ptrace(libc::PTRACE_TRACEME, 0, 0, 0); 7 | } 8 | } 9 | 10 | pub fn continue_until_next_syscall(target_pid: i32) { 11 | unsafe { 12 | libc::ptrace(libc::PTRACE_SYSCALL, target_pid, 0, 0); 13 | } 14 | } 15 | 16 | pub fn continue_and_wait_until_next_syscall(target_pid: i32) { 17 | continue_until_next_syscall(target_pid); 18 | unsafe { 19 | libc::wait(std::ptr::null_mut()); 20 | } 21 | } 22 | 23 | pub fn singlestep(target_pid: i32) { 24 | unsafe { 25 | libc::ptrace(libc::PTRACE_SINGLESTEP, target_pid, 0, 0); 26 | } 27 | } 28 | 29 | pub fn cont(target_pid: i32) { 30 | unsafe { 31 | libc::ptrace(libc::PTRACE_CONT, target_pid, 0, 0); 32 | } 33 | } 34 | 35 | pub fn peek_word(target_pid: i32, addr: u64) -> Result { 36 | unsafe { 37 | *libc::__errno_location() = 0; 38 | let word: i64 = libc::ptrace(libc::PTRACE_PEEKTEXT, target_pid, addr, 0); 39 | if word == -1 && *libc::__errno_location() != 0 { 40 | return Err(*libc::__errno_location()); 41 | } else { 42 | return Ok(word as u64); 43 | } 44 | } 45 | } 46 | 47 | pub fn poke_word(target_pid: i32, addr: u64, data: u64) { 48 | unsafe { 49 | libc::ptrace(libc::PTRACE_POKETEXT, target_pid, addr, data); 50 | } 51 | } 52 | 53 | pub fn get_user_struct(target_pid: i32, user_struct: *mut libc::user) { 54 | unsafe { 55 | libc::ptrace(libc::PTRACE_GETREGS, target_pid, 0, user_struct); 56 | } 57 | } 58 | 59 | pub fn write_user_struct(target_pid: i32, user_struct: *const libc::user) { 60 | unsafe { 61 | libc::ptrace(libc::PTRACE_SETREGS, target_pid, 0, user_struct); 62 | } 63 | } 64 | 65 | pub fn read_user(target_pid: i32, reg_id: i32) -> Result { 66 | unsafe { 67 | /* clear errno */ 68 | *libc::__errno_location() = 0; 69 | let ret = libc::ptrace(libc::PTRACE_PEEKUSER, target_pid, 8 * reg_id, 0); 70 | if ret == -1 && *libc::__errno_location() != 0 { 71 | return Err(*libc::__errno_location()); 72 | } else { 73 | return Ok(ret); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /talk_dbg/src/target/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate libc; 2 | use std; 3 | use std::ffi::{CString}; 4 | 5 | use super::ptrace; 6 | 7 | #[derive(PartialEq, Eq)] 8 | pub enum ProgramState { 9 | Fresh, 10 | Running, 11 | Stopped, 12 | Failed, 13 | Exited, 14 | } 15 | 16 | pub const PRG_FLAG_IN_SYSCALL: u32 = (1 << 0); 17 | 18 | #[derive(Clone)] 19 | struct BreakpointData { 20 | addr: u64, 21 | orig_byte: u8, 22 | } 23 | 24 | pub struct TargetProgram { 25 | pub target_pid: i32, 26 | pub target_executable: String, 27 | pub state: ProgramState, 28 | pub flags: u32, 29 | breakpoints: Vec, 30 | } 31 | 32 | impl TargetProgram { 33 | 34 | pub fn new(target_pid: i32, target: &String) -> TargetProgram { 35 | TargetProgram { 36 | target_pid: target_pid, 37 | target_executable: (*target).clone(), 38 | state: ProgramState::Fresh, 39 | flags: 0, 40 | breakpoints: Vec::new(), 41 | } 42 | } 43 | 44 | pub fn run(&mut self) { 45 | unsafe { 46 | /* tell the kernel that we want to be traced */ 47 | ptrace::trace_me(); 48 | 49 | /* create a C String version of the target */ 50 | let ctarget_m = CString::new((self.target_executable).clone()).unwrap(); 51 | let ctarget = ctarget_m.as_ptr(); 52 | 53 | /* prepare the argv */ 54 | let mut vec_argv: Vec<*const i8> = Vec::new(); 55 | vec_argv.push(ctarget); 56 | vec_argv.push(std::ptr::null()); 57 | 58 | /* prepare the environment */ 59 | let mut vec_envv: Vec<*const i8> = Vec::new(); 60 | vec_envv.push(CString::new("HOME=/vagrant").unwrap().as_ptr()); 61 | vec_envv.push(std::ptr::null()); 62 | 63 | self.state = ProgramState::Running; 64 | 65 | /* start the application */ 66 | let ret = libc::execve(ctarget, vec_argv.as_ptr(), vec_envv.as_ptr()); 67 | 68 | self.state = ProgramState::Failed; 69 | 70 | /* oops, it failed to run */ 71 | println!("TRG: failed to run, exited with err {} and errno {}", ret, *libc::__errno_location()); 72 | } 73 | } 74 | 75 | pub fn kill(&mut self) { 76 | unsafe { 77 | libc::kill(self.target_pid, libc::SIGKILL); 78 | } 79 | self.state = ProgramState::Exited; 80 | } 81 | 82 | pub fn wait(&self) -> u32 { 83 | let mut status: i32 = 0; 84 | 85 | unsafe { 86 | /* wait for the next ptrace induced block */ 87 | libc::waitpid(-1, &mut status, 0); 88 | } 89 | 90 | return status as u32; 91 | } 92 | 93 | pub fn read_user(&mut self, reg_id: i32) -> Result { 94 | return ptrace::read_user(self.target_pid, reg_id); 95 | } 96 | 97 | pub fn singlestep(&mut self) { 98 | self.state = ProgramState::Running; 99 | ptrace::singlestep(self.target_pid); 100 | } 101 | 102 | pub fn cont(&mut self) { 103 | self.state = ProgramState::Running; 104 | ptrace::cont(self.target_pid); 105 | } 106 | 107 | pub fn continue_and_wait_until_next_syscall(&mut self) { 108 | ptrace::continue_and_wait_until_next_syscall(self.target_pid); 109 | self.state = ProgramState::Stopped; 110 | } 111 | 112 | pub fn peek_byte_at(&mut self, location: u64) -> u8 { 113 | /* align to 8 bytes */ 114 | let loc = (location / 8) * 8; 115 | let offset = location % 8; 116 | let word: Result = ptrace::peek_word(self.target_pid, loc); 117 | match word { 118 | Ok(w) => return ((w & (0xff << (8 * offset))) >> (8 * offset)) as u8, 119 | Err(err) => 120 | panic!("failed to read byte at {:016x} errno: {}", loc, err), 121 | } 122 | } 123 | 124 | pub fn poke_byte_at(&mut self, location: u64, data: u8) { 125 | let loc = (location / 8) * 8; 126 | let offset = location % 8; 127 | let mut word: u64 = ptrace::peek_word(self.target_pid, loc) 128 | .ok() 129 | .expect("OOPS"); 130 | word = (word & !(0xff << (8 * offset))) | ((data as u64) << (8 * offset)); 131 | ptrace::poke_word(self.target_pid, loc, word); 132 | } 133 | 134 | pub fn get_user_struct(&mut self) -> libc::user { 135 | unsafe { 136 | let mut user_struct: libc::user = std::mem::uninitialized(); 137 | ptrace::get_user_struct(self.target_pid, &mut user_struct); 138 | return user_struct; 139 | } 140 | } 141 | 142 | pub fn write_user_struct(&mut self, usr: libc::user) { 143 | ptrace::write_user_struct(self.target_pid, &usr); 144 | } 145 | 146 | pub fn list_breakpoints(&mut self) { 147 | if self.breakpoints.len() == 0 { 148 | println!("No breakpoints set yet"); 149 | return; 150 | } 151 | for i in 0..self.breakpoints.len() { 152 | let bp: BreakpointData = self.breakpoints[i].clone(); 153 | 154 | println!("Breakpoint {} at 0x{:016x}", i, bp.addr); 155 | } 156 | } 157 | 158 | pub fn set_breakpoint(&mut self, loc: u64) { 159 | let orig_byte: u8 = self.peek_byte_at(loc); 160 | 161 | /* 0xCC is the machine code int $3 */ 162 | self.poke_byte_at(loc, 0xCC); 163 | 164 | self.breakpoints.push(BreakpointData { 165 | addr: loc, 166 | orig_byte: orig_byte, 167 | }); 168 | } 169 | 170 | pub fn handle_breakpoint(&mut self) { 171 | let mut user: libc::user = self.get_user_struct(); 172 | let rip: u64 = user.regs.rip - 1; 173 | 174 | for i in 0..self.breakpoints.len() { 175 | let bp = self.breakpoints[i].clone(); 176 | 177 | if bp.addr == rip { 178 | self.poke_byte_at(bp.addr, bp.orig_byte); 179 | 180 | user.regs.rip = rip; 181 | self.write_user_struct(user); 182 | return; 183 | } 184 | } 185 | 186 | panic!("oops"); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /test_program/Makefile: -------------------------------------------------------------------------------- 1 | guess: main.c 2 | gcc -g main.c -o guess 3 | -------------------------------------------------------------------------------- /test_program/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static int target; 6 | 7 | void 8 | game(void) 9 | { 10 | target = rand() % 100; 11 | 12 | while(1) { 13 | int guess, n; 14 | printf("Make a guess: "); 15 | n = scanf("%d", &guess); 16 | if (n <= 0) 17 | break; 18 | 19 | if (guess > target) { 20 | printf("It's lower!\n"); 21 | } else if (guess < target) { 22 | printf("It's higher!\n"); 23 | } else { 24 | printf("You've got it!\n"); 25 | break; 26 | } 27 | } 28 | } 29 | 30 | int 31 | main(int argc, char **argv) 32 | { 33 | srand(time(NULL)); 34 | 35 | printf("Hello, SCALE 16x!\n"); 36 | 37 | game(); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /vagrant_bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | apt-get update 4 | apt-get install -y curl wget build-essential git libcapstone3 libcapstone-dev 5 | curl https://sh.rustup.rs -sSf > rustup.sh 6 | sh rustup.sh -y 7 | echo "export PATH=$HOME/.cargo/bin:$PATH" >> ~/.bashrc 8 | --------------------------------------------------------------------------------