WHEN GDB IS NOT ENOUGH PAUL SEMEL KEVIN TAVUKCIYAN TALKING ABOUT - - PowerPoint PPT Presentation

when gdb is not enough
SMART_READER_LITE
LIVE PREVIEW

WHEN GDB IS NOT ENOUGH PAUL SEMEL KEVIN TAVUKCIYAN TALKING ABOUT - - PowerPoint PPT Presentation

WHEN GDB IS NOT ENOUGH PAUL SEMEL KEVIN TAVUKCIYAN TALKING ABOUT DWARF TALKING ABOUT DWARF DEBUGGING WITH ATTRIBUTE RECORD FORMATS WHAT IS DWARF? WHAT IS DWARF? Format used to store debug informations Generated by the compiler Sections in


slide-1
SLIDE 1

WHEN GDB IS NOT ENOUGH

PAUL SEMEL KEVIN TAVUKCIYAN

slide-2
SLIDE 2

TALKING ABOUT DWARF

slide-3
SLIDE 3

TALKING ABOUT DWARF

DEBUGGING WITH ATTRIBUTE RECORD FORMATS

slide-4
SLIDE 4

WHAT IS DWARF?

slide-5
SLIDE 5

WHAT IS DWARF? Format used to store debug informations Generated by the compiler Sections in the binary format

slide-6
SLIDE 6

HOW DOES IT WORK?

slide-7
SLIDE 7

INFO

Contains all information on our types Informations are sorted by compilation units. Info entry are called DIE (Dwarf Info Entry).

slide-8
SLIDE 8

COMPILATION UNIT

Interesting projects have more than one source code le and are compiled separately and linked together They are called Compilation Unit in DWARF Each DIE are different and separated by compile units

slide-9
SLIDE 9

DIE (SOUNDS APPEALING ALREADY HUH?)

Basic description entry in DWARF Has a tag which precises what it describes Can describe data or functions/executable code

slide-10
SLIDE 10

ABBREV

Table of abbreviation Used to compress data inside the section Contains info on the content of the DIE

slide-11
SLIDE 11

APPLICATIONS

slide-12
SLIDE 12

GNU BINUTILS Multiple DWARF4 parsing implementation Too deeply merged in the rest of the projects 10k+ LOC in objdump / 25k+ LOC in gdb

slide-13
SLIDE 13

OUR PROJECT

slide-14
SLIDE 14

DWARF PRETTYPRINTER

Get structure members. Print structure content. 1500 LOC : Deal with it Stallman !

slide-15
SLIDE 15

WHAT WAS THE POINT OF THE PROJECT?

Create a lib that can print the structure when given a pointer to it. Useful for debug when gdb is too much. As fast and as lightweight as possible.

slide-16
SLIDE 16

TECHNIQUES USED

slide-17
SLIDE 17

DWARF FORMAT PARSING DWARF format is against us. We needed a technique to avoid loading the whole DWARF tree in memory

slide-18
SLIDE 18
slide-19
SLIDE 19

WHAT'S WRONG WITH THIS ? We need to parse the whole format until we nd a DIE. The size of a tag can be variable.

slide-20
SLIDE 20
slide-21
SLIDE 21

SO, HOW CAN WE OPTIMIZE THIS ? We need to x the size of as most tag as we can. If we encounter a structure, we keep it in memory. We remain where we stopped parsing the last time.

slide-22
SLIDE 22
slide-23
SLIDE 23

VISITOR

slide-24
SLIDE 24

WHAT DO WE NEED ? Give depth traversing control to the user. The user must be able to hook everywhere. By default depth traversing and printing functions.

slide-25
SLIDE 25

HOW CAN WE DO THAT ? Each node has a default depth traversing function. We store printing functions in a hash table. Basic types must have a default printing function. The traversing is triggered by the printing function.

slide-26
SLIDE 26

NODE STRUCTURE This is the structure given to the user

struct Die { const char *name; const char *type; void *data; size_t len; struct list children; struct list sibling; void (*next)(struct Die *, struct hash_control *); };

slide-27
SLIDE 27

LET'S TRY IT !

slide-28
SLIDE 28

THE TEST STRUCURE

typedef uint16_t u16; struct example { unsigned short int a; u16 b; };

slide-29
SLIDE 29
slide-30
SLIDE 30

void *init_dwarf(char *path); int print_structure_content(void *address, char *name, void *di, void* ctx); /* * param 1 : ctx may be NULL the first time the function is called * param 2 : name may be NULL if no type specification * param 3 : musn't be NULL * param 4 : print function * * param 1 : Current Die * * param 2 : User data * * param 3 : Must be sent to next() function if called * param 5 : user data */ void *set_context(void *ctx, const char *name, const char *type, void (*print)(Die *, void *, void *), void *data)

slide-31
SLIDE 31

void print_uint16(Die *die, void *data, void *h) { printf("%s %s : %d\n", die->type, die->name, *(unsigned short int *)die->data); } int main(void) { struct example t; t.a = 1234; t.b = 42; void *te = init_dwarf("/proc/self/exe"); void *ctx = NULL; ctx = set_context(NULL, NULL, "uint16_t", print_uint16, NULL); print_structure_content(&t, "example", te, ctx); }

slide-32
SLIDE 32

BY DEFAULT WITH OUR HOOK

struct example : t short unsigned int b : 42 short unsigned int a : 1234 struct example : t uint16_t b : 42 short unsigned int a : 1234

slide-33
SLIDE 33

What's next? Recursive parsing Parse faster when given a compile unit.

slide-34
SLIDE 34

CONCLUSION

slide-35
SLIDE 35

QUESTIONS?