EuroBSDcon 2017
Author: Kamil Rytarowski
E-mail: kamil@netbsd.org
Date: September 24th 2017
Place: Paris, France
Kamil Rytarowski (born 1987)
Krakow, Poland
NetBSD user since 6.1.
The NetBSD Foundation member since 2015.
Work areas: kernel, userland, pkgsrc.
Interest: NetBSD on desktop and in particular NetBSD as a workstation.
The current activity in 3rd party software:
Toolchain - A set of programming development tools for creating a software product.
A basic UNIX toolchain consists of: a compiler, a linker, libraries, and a debugger.
A more complex toolchain may consist of additional elements like disassemblers, profilers, sanitizers etc. An advanced toolchain may ship with 3D-graphics modelers, audio synthetizers etc.
A computer program that can test and trace a computer program in order to assist detection of computer program bugs.
In this presentation we will focus on the system-level debuggers (referring to it as a plain "debugger") designed for general-purpose Operating Systems like UNIX, executing native code with an optional involvement of a simulator.
Debugging is the process of using a tracer and searching for a solution to issues.
A usual workflow using a debugger:
Tracing involves starting & stopping of a process (and threads) and process introspection into memory, register context, thread information etc.
The user-visible result of the process introspection is the state of threads, current line of the code in the program-counter register, status of local variables, stack of function calls with the passed optional arguments etc.
1 (gdb) b fun3
2 Breakpoint 1 at 0x4007e7: file main.c, line 3.
3 (gdb) r
4 Starting program: /tmp/a.out
5
6 Breakpoint 1, fun3 (a=1) at main.c:3
7 3 return a + 1;
8 (gdb) bt
9 #0 fun3 (a=1) at main.c:3
10 #1 0x0000000000400804 in fun2 (a=1) at main.c:8
11 #2 0x000000000040081b in fun (a=1) at main.c:13
12 #3 0x0000000000400836 in main (argc=1, argv=0x7f7fff270fb0) at \
13 main.c:18
Debuggers should support the debugged program's language like C, C++ or Fortran.
A program for better debugging experience should be built with additional debuginfo information and ship with available source code.
1 #include <stdio.h>
2 int main(int argc, char **argv)
3 {
4 printf("Hello world\n");
5
6 return 0;
7 }
Compilation with debug symbols:
1 gcc -g -Og program.c -o program
A debugger runs as a regular process and traces another entity being another process or process image stored on disk (a core file).
Program:
1 $ file /usr/pkg/bin/firefox
2 /usr/pkg/bin/firefox: symbolic link to /usr/pkg/lib/firefox/firefox
3
4 $ file /usr/pkg/lib/firefox/firefox
5 /usr/pkg/lib/firefox/firefox: ELF 64-bit LSB shared object, x86-64, \
6 version 1 (SYSV), dynamically linked, interpreter \
7 /usr/libexec/ld.elf_so, for NetBSD 8.99.2, PaX: -mprotect, \
8 BuildID[sha1]=74d0f5fe231dcc4148656e613fb9c9b45cb9183d, \
9 with debug_info, not stripped
Core file:
1 $ file firefox.core
2 firefox.core: ELF 64-bit LSB core file x86-64, version 1 (SYSV), \
3 NetBSD-style, from 'firefox', pid=1407, uid=1000, gid=100, \
4 nlwps=10, lwp=1 (signal 11/code 32767)
A debugger reuses Operating System and hardware specific features exported in Machine-Dependent style to userspace programs through kernel API.
Unsupported hardware features by a certain (or all) hardware can be reimplemented with a simulator, while the rest executes underlying hardware capabilities.
LLDB is a next generation, high-performance debugger. It is built as a set of reusable components which highly leverage existing libraries in the larger LLVM Project, such as the Clang expression parser and LLVM disassembler.
LLDB is the default debugger in Xcode on Mac OS X and supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
All of the code in the LLDB project is available under the standard LLVM License, an open source "BSD-style" license.
-- Source: http://lldb.llvm.org/
Goals and benefits of porting the LLDB Debugger to NetBSD:
The last point enforced the NetBSD kernel to ship reliable and functional features comparable to Windows, Darwin, Linux (&Android) and FreeBSD. NetBSD 8(beta) is now there in terms of the generic Machine-Independent kernel capabilities, and still not there in terms of reliability and availability of Machine-Dependent parts.
Goals and benefits of porting the LLDB Debugger to NetBSD:
The GNU and LLVM toolchain tools can be treated as two legs on which a modern Operating System like NetBSD should stand. There is competition, but no obsolescence of one because of the other. One set of 3rd party tools will require the former, another set will require the latter.
Goals and benefits of porting the LLDB Debugger to NetBSD:
What to expect when using the new debugger on NetBSD.
Today in the mainline code and the 5.0.0 release:
What to expect when using the new debugger on NetBSD.
Local patches:
LLDB depends on correct and modern support in: Clang, LLVM, userland libraries and kernel.
Everything is supported in the context of certain hardware - that cannot be programically fixed or improved - it must be supported as it is.
While it might be unrelated to LLDB porting effort, I attempt to follow the approach of zero-problems on NetBSD/amd64
LLVM and Clang are important in the process of LLDB/NetBSD porting because:
ptrace(2) - process tracing and debugging facility
By using process trace one process can take over another, inspect and manipulate its register context, address space and control flow.
Underneath this interface is using the reparenting mechanism. The tracer is a new parent, the tracee is a child and userland processes mostly don't notice it.
This interface is used in BSD operating systems and GNU/Linux (kernel) and they are relatively closely related.
The difference between ptrace(2), sysctl(2) and kvm(3):
A process must have the same real UID as the tracing process, and also it must not be executing a setuid or setgid executable. (If the tracing process is running as root: these restrictions do not apply.)
Three restrictions apply to all tracing processes.
In order to put a trap by a tracer into the tracee's program, the debugger must violate the PaX MPROTECT restrictions.
1 $ sysctl -d security.pax.mprotect.ptrace
2 security.pax.mprotect.ptrace: When enabled, allow ptrace(2) to \
3 override mprotect permissions on traced processes
NetBSD
1 int
2 ptrace(int request, pid_t pid, void *addr, int data);
Linux
1 long
2 ptrace(enum __ptrace_request request,
3 pid_t pid, void *addr, void *data);
FreeBSD
1 int
2 ptrace(int request, pid_t pid, caddr_t addr, int data);
OpenBSD
1 int
2 ptrace(int request, pid_t pid, caddr_t addr, int data);
NetBSD
1 #include <sys/types.h>
2 #include <sys/ptrace.h>
Linux
1 #include <sys/ptrace.h>
FreeBSD
1 #include <sys/types.h>
2 #include <sys/ptrace.h>
OpenBSD
1 #include <sys/types.h>
2 #include <sys/ptrace.h>
Resources:
Development policies:
Future-ready policies:
Major changes in the Machine-Independent part:
Major changes in the Machine-Independent part:
Local development through pkgsrc-wip:
NetBSD buildbot
LLVM ships with sanitizers:
asan and ubsan are already functional on NetBSD and fully upstreamed
msan and tsan are work-in-progress
Example source code:
1 int
2 main(int argc, char *argv[])
3 {
4 int abc[2];
5
6 abc[argc + 3] = 123;
7
8 return 0;
9 }
Execution of ubsan:
1 $ /usr/local/bin/clang -fsanitize=undefined 1.c -o 1.undef
2 $ ./1.undef
3 1.c:6:2: runtime error: index 4 out of bounds for type 'int [2]'
Execution of asan:
1 $ /usr/local/bin/clang -fsanitize=address 1.c -o 1.addr
2 $ ./1.addr
3 =================================================================
4 ==25664==ERROR: AddressSanitizer: stack-buffer-overflow on address \
5 0x7f7fffffe650 at pc 0x00000040a359 bp 0x7f7fffffe610 sp 0x7f7fffffe608
6 WRITE of size 4 at 0x7f7fffffe650 thread T0
7 #0 0x40a358 in main (/tmp/1.addr+0x40a358)
8 #1 0x40a13a in ___start (/tmp/1.addr+0x40a13a)
9
10 Address 0x7f7fffffe650 is located in stack of thread T0 at offset 48 \
11 in frame
12 #0 0x40a22f in main (/tmp/1.addr+0x40a22f)
13
14 This frame has 1 object(s):
15 [32, 40) 'abc' <== Memory access at offset 48 overflows this \
16 variable
17 [... memory dump here, hints etc ...]
libFuzzer and SafeStack have been ported to NetBSD and upstreamed.
SafeStack is a software security hardening technique that creates two stacks: one for data that needs to be kept safe, such as return addresses and function pointers; and an unsafe stack for everything else.
LLVM libFuzzer is an in-process, coverage-guided, evolutionary fuzzing engine. As of now libFuzzer requires for more sanitizers to get aboard to NetBSD, especially lsan (Leak Sanitizer).
The NetBSD Foundation - for sponsoring the project.
The NetBSD developers and in particular Christos Zoulas, Martin Husemann, Thomas Klausner, K.Robert Elz, Nicolas Joly, Paul Goyette for help with code fixes, feedback and bug reports.
Navigare necesse est, vivere non est necesse
"to sail is necessary; to live is not necessary"
-- Gnaeus Pompeius Magnus minor
Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |