linux/tools/perf/util/genelf_debug.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * genelf_debug.c
   4 * Copyright (C) 2015, Google, Inc
   5 *
   6 * Contributed by:
   7 *      Stephane Eranian <eranian@google.com>
   8 *
   9 * based on GPLv2 source code from Oprofile
  10 * @remark Copyright 2007 OProfile authors
  11 * @author Philippe Elie
  12 */
  13#include <linux/compiler.h>
  14#include <sys/types.h>
  15#include <stdio.h>
  16#include <getopt.h>
  17#include <stddef.h>
  18#include <libelf.h>
  19#include <string.h>
  20#include <stdlib.h>
  21#include <inttypes.h>
  22#include <limits.h>
  23#include <fcntl.h>
  24#include <err.h>
  25#include <dwarf.h>
  26
  27#include "perf.h"
  28#include "genelf.h"
  29#include "../util/jitdump.h"
  30
  31#define BUFFER_EXT_DFL_SIZE     (4 * 1024)
  32
  33typedef uint32_t uword;
  34typedef uint16_t uhalf;
  35typedef int32_t  sword;
  36typedef int16_t  shalf;
  37typedef uint8_t  ubyte;
  38typedef int8_t   sbyte;
  39
  40struct buffer_ext {
  41        size_t cur_pos;
  42        size_t max_sz;
  43        void *data;
  44};
  45
  46static void
  47buffer_ext_dump(struct buffer_ext *be, const char *msg)
  48{
  49        size_t i;
  50        warnx("DUMP for %s", msg);
  51        for (i = 0 ; i < be->cur_pos; i++)
  52                warnx("%4zu 0x%02x", i, (((char *)be->data)[i]) & 0xff);
  53}
  54
  55static inline int
  56buffer_ext_add(struct buffer_ext *be, void *addr, size_t sz)
  57{
  58        void *tmp;
  59        size_t be_sz = be->max_sz;
  60
  61retry:
  62        if ((be->cur_pos + sz) < be_sz) {
  63                memcpy(be->data + be->cur_pos, addr, sz);
  64                be->cur_pos += sz;
  65                return 0;
  66        }
  67
  68        if (!be_sz)
  69                be_sz = BUFFER_EXT_DFL_SIZE;
  70        else
  71                be_sz <<= 1;
  72
  73        tmp = realloc(be->data, be_sz);
  74        if (!tmp)
  75                return -1;
  76
  77        be->data   = tmp;
  78        be->max_sz = be_sz;
  79
  80        goto retry;
  81}
  82
  83static void
  84buffer_ext_init(struct buffer_ext *be)
  85{
  86        be->data = NULL;
  87        be->cur_pos = 0;
  88        be->max_sz = 0;
  89}
  90
  91static inline size_t
  92buffer_ext_size(struct buffer_ext *be)
  93{
  94        return be->cur_pos;
  95}
  96
  97static inline void *
  98buffer_ext_addr(struct buffer_ext *be)
  99{
 100        return be->data;
 101}
 102
 103struct debug_line_header {
 104        // Not counting this field
 105        uword total_length;
 106        // version number (2 currently)
 107        uhalf version;
 108        // relative offset from next field to
 109        // program statement
 110        uword prolog_length;
 111        ubyte minimum_instruction_length;
 112        ubyte default_is_stmt;
 113        // line_base - see DWARF 2 specs
 114        sbyte line_base;
 115        // line_range - see DWARF 2 specs
 116        ubyte line_range;
 117        // number of opcode + 1
 118        ubyte opcode_base;
 119        /* follow the array of opcode args nr: ubytes [nr_opcode_base] */
 120        /* follow the search directories index, zero terminated string
 121         * terminated by an empty string.
 122         */
 123        /* follow an array of { filename, LEB128, LEB128, LEB128 }, first is
 124         * the directory index entry, 0 means current directory, then mtime
 125         * and filesize, last entry is followed by en empty string.
 126         */
 127        /* follow the first program statement */
 128} __packed;
 129
 130/* DWARF 2 spec talk only about one possible compilation unit header while
 131 * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not
 132 * related to the used arch, an ELF 32 can hold more than 4 Go of debug
 133 * information. For now we handle only DWARF 2 32 bits comp unit. It'll only
 134 * become a problem if we generate more than 4GB of debug information.
 135 */
 136struct compilation_unit_header {
 137        uword total_length;
 138        uhalf version;
 139        uword debug_abbrev_offset;
 140        ubyte pointer_size;
 141} __packed;
 142
 143#define DW_LNS_num_opcode (DW_LNS_set_isa + 1)
 144
 145/* field filled at run time are marked with -1 */
 146static struct debug_line_header const default_debug_line_header = {
 147        .total_length = -1,
 148        .version = 2,
 149        .prolog_length = -1,
 150        .minimum_instruction_length = 1,        /* could be better when min instruction size != 1 */
 151        .default_is_stmt = 1,   /* we don't take care about basic block */
 152        .line_base = -5,        /* sensible value for line base ... */
 153        .line_range = -14,     /* ... and line range are guessed statically */
 154        .opcode_base = DW_LNS_num_opcode
 155};
 156
 157static ubyte standard_opcode_length[] =
 158{
 159        0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1
 160};
 161#if 0
 162{
 163        [DW_LNS_advance_pc]   = 1,
 164        [DW_LNS_advance_line] = 1,
 165        [DW_LNS_set_file] =  1,
 166        [DW_LNS_set_column] = 1,
 167        [DW_LNS_fixed_advance_pc] = 1,
 168        [DW_LNS_set_isa] = 1,
 169};
 170#endif
 171
 172/* field filled at run time are marked with -1 */
 173static struct compilation_unit_header default_comp_unit_header = {
 174        .total_length = -1,
 175        .version = 2,
 176        .debug_abbrev_offset = 0,     /* we reuse the same abbrev entries for all comp unit */
 177        .pointer_size = sizeof(void *)
 178};
 179
 180static void emit_uword(struct buffer_ext *be, uword data)
 181{
 182        buffer_ext_add(be, &data, sizeof(uword));
 183}
 184
 185static void emit_string(struct buffer_ext *be, const char *s)
 186{
 187        buffer_ext_add(be, (void *)s, strlen(s) + 1);
 188}
 189
 190static void emit_unsigned_LEB128(struct buffer_ext *be,
 191                                 unsigned long data)
 192{
 193        do {
 194                ubyte cur = data & 0x7F;
 195                data >>= 7;
 196                if (data)
 197                        cur |= 0x80;
 198                buffer_ext_add(be, &cur, 1);
 199        } while (data);
 200}
 201
 202static void emit_signed_LEB128(struct buffer_ext *be, long data)
 203{
 204        int more = 1;
 205        int negative = data < 0;
 206        int size = sizeof(long) * CHAR_BIT;
 207        while (more) {
 208                ubyte cur = data & 0x7F;
 209                data >>= 7;
 210                if (negative)
 211                        data |= - (1 << (size - 7));
 212                if ((data == 0 && !(cur & 0x40)) ||
 213                    (data == -1l && (cur & 0x40)))
 214                        more = 0;
 215                else
 216                        cur |= 0x80;
 217                buffer_ext_add(be, &cur, 1);
 218        }
 219}
 220
 221static void emit_extended_opcode(struct buffer_ext *be, ubyte opcode,
 222                                 void *data, size_t data_len)
 223{
 224        buffer_ext_add(be, (char *)"", 1);
 225
 226        emit_unsigned_LEB128(be, data_len + 1);
 227
 228        buffer_ext_add(be, &opcode, 1);
 229        buffer_ext_add(be, data, data_len);
 230}
 231
 232static void emit_opcode(struct buffer_ext *be, ubyte opcode)
 233{
 234        buffer_ext_add(be, &opcode, 1);
 235}
 236
 237static void emit_opcode_signed(struct buffer_ext  *be,
 238                               ubyte opcode, long data)
 239{
 240        buffer_ext_add(be, &opcode, 1);
 241        emit_signed_LEB128(be, data);
 242}
 243
 244static void emit_opcode_unsigned(struct buffer_ext *be, ubyte opcode,
 245                                 unsigned long data)
 246{
 247        buffer_ext_add(be, &opcode, 1);
 248        emit_unsigned_LEB128(be, data);
 249}
 250
 251static void emit_advance_pc(struct buffer_ext *be, unsigned long delta_pc)
 252{
 253        emit_opcode_unsigned(be, DW_LNS_advance_pc, delta_pc);
 254}
 255
 256static void emit_advance_lineno(struct buffer_ext  *be, long delta_lineno)
 257{
 258        emit_opcode_signed(be, DW_LNS_advance_line, delta_lineno);
 259}
 260
 261static void emit_lne_end_of_sequence(struct buffer_ext *be)
 262{
 263        emit_extended_opcode(be, DW_LNE_end_sequence, NULL, 0);
 264}
 265
 266static void emit_set_file(struct buffer_ext *be, unsigned long idx)
 267{
 268        emit_opcode_unsigned(be, DW_LNS_set_file, idx);
 269}
 270
 271static void emit_lne_define_filename(struct buffer_ext *be,
 272                                     const char *filename)
 273{
 274        buffer_ext_add(be, (void *)"", 1);
 275
 276        /* LNE field, strlen(filename) + zero termination, 3 bytes for: the dir entry, timestamp, filesize */
 277        emit_unsigned_LEB128(be, strlen(filename) + 5);
 278        emit_opcode(be, DW_LNE_define_file);
 279        emit_string(be, filename);
 280        /* directory index 0=do not know */
 281        emit_unsigned_LEB128(be, 0);
 282        /* last modification date on file 0=do not know */
 283        emit_unsigned_LEB128(be, 0);
 284        /* filesize 0=do not know */
 285        emit_unsigned_LEB128(be, 0);
 286}
 287
 288static void emit_lne_set_address(struct buffer_ext *be,
 289                                 void *address)
 290{
 291        emit_extended_opcode(be, DW_LNE_set_address, &address, sizeof(unsigned long));
 292}
 293
 294static ubyte get_special_opcode(struct debug_entry *ent,
 295                                unsigned int last_line,
 296                                unsigned long last_vma)
 297{
 298        unsigned int temp;
 299        unsigned long delta_addr;
 300
 301        /*
 302         * delta from line_base
 303         */
 304        temp = (ent->lineno - last_line) - default_debug_line_header.line_base;
 305
 306        if (temp >= default_debug_line_header.line_range)
 307                return 0;
 308
 309        /*
 310         * delta of addresses
 311         */
 312        delta_addr = (ent->addr - last_vma) / default_debug_line_header.minimum_instruction_length;
 313
 314        /* This is not sufficient to ensure opcode will be in [0-256] but
 315         * sufficient to ensure when summing with the delta lineno we will
 316         * not overflow the unsigned long opcode */
 317
 318        if (delta_addr <= 256 / default_debug_line_header.line_range) {
 319                unsigned long opcode = temp +
 320                        (delta_addr * default_debug_line_header.line_range) +
 321                        default_debug_line_header.opcode_base;
 322
 323                return opcode <= 255 ? opcode : 0;
 324        }
 325        return 0;
 326}
 327
 328static void emit_lineno_info(struct buffer_ext *be,
 329                             struct debug_entry *ent, size_t nr_entry,
 330                             unsigned long code_addr)
 331{
 332        size_t i;
 333
 334        /*
 335         * Machine state at start of a statement program
 336         * address = 0
 337         * file    = 1
 338         * line    = 1
 339         * column  = 0
 340         * is_stmt = default_is_stmt as given in the debug_line_header
 341         * basic block = 0
 342         * end sequence = 0
 343         */
 344
 345        /* start state of the state machine we take care of */
 346        unsigned long last_vma = code_addr;
 347        char const  *cur_filename = NULL;
 348        unsigned long cur_file_idx = 0;
 349        int last_line = 1;
 350
 351        emit_lne_set_address(be, (void *)code_addr);
 352
 353        for (i = 0; i < nr_entry; i++, ent = debug_entry_next(ent)) {
 354                int need_copy = 0;
 355                ubyte special_opcode;
 356
 357                /*
 358                 * check if filename changed, if so add it
 359                 */
 360                if (!cur_filename || strcmp(cur_filename, ent->name)) {
 361                        emit_lne_define_filename(be, ent->name);
 362                        cur_filename = ent->name;
 363                        emit_set_file(be, ++cur_file_idx);
 364                        need_copy = 1;
 365                }
 366
 367                special_opcode = get_special_opcode(ent, last_line, last_vma);
 368                if (special_opcode != 0) {
 369                        last_line = ent->lineno;
 370                        last_vma  = ent->addr;
 371                        emit_opcode(be, special_opcode);
 372                } else {
 373                        /*
 374                         * lines differ, emit line delta
 375                         */
 376                        if (last_line != ent->lineno) {
 377                                emit_advance_lineno(be, ent->lineno - last_line);
 378                                last_line = ent->lineno;
 379                                need_copy = 1;
 380                        }
 381                        /*
 382                         * addresses differ, emit address delta
 383                         */
 384                        if (last_vma != ent->addr) {
 385                                emit_advance_pc(be, ent->addr - last_vma);
 386                                last_vma = ent->addr;
 387                                need_copy = 1;
 388                        }
 389                        /*
 390                         * add new row to matrix
 391                         */
 392                        if (need_copy)
 393                                emit_opcode(be, DW_LNS_copy);
 394                }
 395        }
 396}
 397
 398static void add_debug_line(struct buffer_ext *be,
 399        struct debug_entry *ent, size_t nr_entry,
 400        unsigned long code_addr)
 401{
 402        struct debug_line_header * dbg_header;
 403        size_t old_size;
 404
 405        old_size = buffer_ext_size(be);
 406
 407        buffer_ext_add(be, (void *)&default_debug_line_header,
 408                 sizeof(default_debug_line_header));
 409
 410        buffer_ext_add(be, &standard_opcode_length,  sizeof(standard_opcode_length));
 411
 412        // empty directory entry
 413        buffer_ext_add(be, (void *)"", 1);
 414
 415        // empty filename directory
 416        buffer_ext_add(be, (void *)"", 1);
 417
 418        dbg_header = buffer_ext_addr(be) + old_size;
 419        dbg_header->prolog_length = (buffer_ext_size(be) - old_size) -
 420                offsetof(struct debug_line_header, minimum_instruction_length);
 421
 422        emit_lineno_info(be, ent, nr_entry, code_addr);
 423
 424        emit_lne_end_of_sequence(be);
 425
 426        dbg_header = buffer_ext_addr(be) + old_size;
 427        dbg_header->total_length = (buffer_ext_size(be) - old_size) -
 428                offsetof(struct debug_line_header, version);
 429}
 430
 431static void
 432add_debug_abbrev(struct buffer_ext *be)
 433{
 434        emit_unsigned_LEB128(be, 1);
 435        emit_unsigned_LEB128(be, DW_TAG_compile_unit);
 436        emit_unsigned_LEB128(be, DW_CHILDREN_yes);
 437        emit_unsigned_LEB128(be, DW_AT_stmt_list);
 438        emit_unsigned_LEB128(be, DW_FORM_data4);
 439        emit_unsigned_LEB128(be, 0);
 440        emit_unsigned_LEB128(be, 0);
 441        emit_unsigned_LEB128(be, 0);
 442}
 443
 444static void
 445add_compilation_unit(struct buffer_ext *be,
 446                     size_t offset_debug_line)
 447{
 448        struct compilation_unit_header *comp_unit_header;
 449        size_t old_size = buffer_ext_size(be);
 450
 451        buffer_ext_add(be, &default_comp_unit_header,
 452                       sizeof(default_comp_unit_header));
 453
 454        emit_unsigned_LEB128(be, 1);
 455        emit_uword(be, offset_debug_line);
 456
 457        comp_unit_header = buffer_ext_addr(be) + old_size;
 458        comp_unit_header->total_length = (buffer_ext_size(be) - old_size) -
 459                offsetof(struct compilation_unit_header, version);
 460}
 461
 462static int
 463jit_process_debug_info(uint64_t code_addr,
 464                       void *debug, int nr_debug_entries,
 465                       struct buffer_ext *dl,
 466                       struct buffer_ext *da,
 467                       struct buffer_ext *di)
 468{
 469        struct debug_entry *ent = debug;
 470        int i;
 471
 472        for (i = 0; i < nr_debug_entries; i++) {
 473                ent->addr = ent->addr - code_addr;
 474                ent = debug_entry_next(ent);
 475        }
 476        add_compilation_unit(di, buffer_ext_size(dl));
 477        add_debug_line(dl, debug, nr_debug_entries, 0);
 478        add_debug_abbrev(da);
 479        if (0) buffer_ext_dump(da, "abbrev");
 480
 481        return 0;
 482}
 483
 484int
 485jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries)
 486{
 487        Elf_Data *d;
 488        Elf_Scn *scn;
 489        Elf_Shdr *shdr;
 490        struct buffer_ext dl, di, da;
 491        int ret;
 492
 493        buffer_ext_init(&dl);
 494        buffer_ext_init(&di);
 495        buffer_ext_init(&da);
 496
 497        ret = jit_process_debug_info(code_addr, debug, nr_debug_entries, &dl, &da, &di);
 498        if (ret)
 499                return -1;
 500        /*
 501         * setup .debug_line section
 502         */
 503        scn = elf_newscn(e);
 504        if (!scn) {
 505                warnx("cannot create section");
 506                return -1;
 507        }
 508
 509        d = elf_newdata(scn);
 510        if (!d) {
 511                warnx("cannot get new data");
 512                return -1;
 513        }
 514
 515        d->d_align = 1;
 516        d->d_off = 0LL;
 517        d->d_buf = buffer_ext_addr(&dl);
 518        d->d_type = ELF_T_BYTE;
 519        d->d_size = buffer_ext_size(&dl);
 520        d->d_version = EV_CURRENT;
 521
 522        shdr = elf_getshdr(scn);
 523        if (!shdr) {
 524                warnx("cannot get section header");
 525                return -1;
 526        }
 527
 528        shdr->sh_name = 52; /* .debug_line */
 529        shdr->sh_type = SHT_PROGBITS;
 530        shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
 531        shdr->sh_flags = 0;
 532        shdr->sh_entsize = 0;
 533
 534        /*
 535         * setup .debug_info section
 536         */
 537        scn = elf_newscn(e);
 538        if (!scn) {
 539                warnx("cannot create section");
 540                return -1;
 541        }
 542
 543        d = elf_newdata(scn);
 544        if (!d) {
 545                warnx("cannot get new data");
 546                return -1;
 547        }
 548
 549        d->d_align = 1;
 550        d->d_off = 0LL;
 551        d->d_buf = buffer_ext_addr(&di);
 552        d->d_type = ELF_T_BYTE;
 553        d->d_size = buffer_ext_size(&di);
 554        d->d_version = EV_CURRENT;
 555
 556        shdr = elf_getshdr(scn);
 557        if (!shdr) {
 558                warnx("cannot get section header");
 559                return -1;
 560        }
 561
 562        shdr->sh_name = 64; /* .debug_info */
 563        shdr->sh_type = SHT_PROGBITS;
 564        shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
 565        shdr->sh_flags = 0;
 566        shdr->sh_entsize = 0;
 567
 568        /*
 569         * setup .debug_abbrev section
 570         */
 571        scn = elf_newscn(e);
 572        if (!scn) {
 573                warnx("cannot create section");
 574                return -1;
 575        }
 576
 577        d = elf_newdata(scn);
 578        if (!d) {
 579                warnx("cannot get new data");
 580                return -1;
 581        }
 582
 583        d->d_align = 1;
 584        d->d_off = 0LL;
 585        d->d_buf = buffer_ext_addr(&da);
 586        d->d_type = ELF_T_BYTE;
 587        d->d_size = buffer_ext_size(&da);
 588        d->d_version = EV_CURRENT;
 589
 590        shdr = elf_getshdr(scn);
 591        if (!shdr) {
 592                warnx("cannot get section header");
 593                return -1;
 594        }
 595
 596        shdr->sh_name = 76; /* .debug_info */
 597        shdr->sh_type = SHT_PROGBITS;
 598        shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
 599        shdr->sh_flags = 0;
 600        shdr->sh_entsize = 0;
 601
 602        /*
 603         * now we update the ELF image with all the sections
 604         */
 605        if (elf_update(e, ELF_C_WRITE) < 0) {
 606                warnx("elf_update debug failed");
 607                return -1;
 608        }
 609        return 0;
 610}
 611