diff options
Diffstat (limited to 'tools/perf/util/genelf.c')
-rw-r--r-- | tools/perf/util/genelf.c | 102 |
1 files changed, 99 insertions, 3 deletions
diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c index 30dece345b9f..c540d47583e7 100644 --- a/tools/perf/util/genelf.c +++ b/tools/perf/util/genelf.c @@ -73,6 +73,8 @@ static char shd_string_table[] = { '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */ '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */ '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */ + '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */ + '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */ }; static struct buildid_note { @@ -153,6 +155,86 @@ gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *cod } #endif +static int +jit_add_eh_frame_info(Elf *e, void* unwinding, uint64_t unwinding_header_size, + uint64_t unwinding_size, uint64_t base_offset) +{ + Elf_Data *d; + Elf_Scn *scn; + Elf_Shdr *shdr; + uint64_t unwinding_table_size = unwinding_size - unwinding_header_size; + + /* + * setup eh_frame section + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + return -1; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + return -1; + } + + d->d_align = 8; + d->d_off = 0LL; + d->d_buf = unwinding; + d->d_type = ELF_T_BYTE; + d->d_size = unwinding_table_size; + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + return -1; + } + + shdr->sh_name = 104; + shdr->sh_type = SHT_PROGBITS; + shdr->sh_addr = base_offset; + shdr->sh_flags = SHF_ALLOC; + shdr->sh_entsize = 0; + + /* + * setup eh_frame_hdr section + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + return -1; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + return -1; + } + + d->d_align = 4; + d->d_off = 0LL; + d->d_buf = unwinding + unwinding_table_size; + d->d_type = ELF_T_BYTE; + d->d_size = unwinding_header_size; + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + return -1; + } + + shdr->sh_name = 90; + shdr->sh_type = SHT_PROGBITS; + shdr->sh_addr = base_offset + unwinding_table_size; + shdr->sh_flags = SHF_ALLOC; + shdr->sh_entsize = 0; + + return 0; +} + /* * fd: file descriptor open for writing for the output file * load_addr: code load address (could be zero, just used for buildid) @@ -163,13 +245,15 @@ gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *cod int jit_write_elf(int fd, uint64_t load_addr, const char *sym, const void *code, int csize, - void *debug __maybe_unused, int nr_debug_entries __maybe_unused) + void *debug __maybe_unused, int nr_debug_entries __maybe_unused, + void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size) { Elf *e; Elf_Data *d; Elf_Scn *scn; Elf_Ehdr *ehdr; Elf_Shdr *shdr; + uint64_t eh_frame_base_offset; char *strsym = NULL; int symlen; int retval = -1; @@ -200,7 +284,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym, ehdr->e_type = ET_DYN; ehdr->e_entry = GEN_ELF_TEXT_OFFSET; ehdr->e_version = EV_CURRENT; - ehdr->e_shstrndx= 2; /* shdr index for section name */ + ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */ /* * setup text section @@ -237,6 +321,18 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym, shdr->sh_entsize = 0; /* + * Setup .eh_frame_hdr and .eh_frame + */ + if (unwinding) { + eh_frame_base_offset = ALIGN_8(GEN_ELF_TEXT_OFFSET + csize); + retval = jit_add_eh_frame_info(e, unwinding, + unwinding_header_size, unwinding_size, + eh_frame_base_offset); + if (retval) + goto error; + } + + /* * setup section headers string table */ scn = elf_newscn(e); @@ -304,7 +400,7 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym, shdr->sh_type = SHT_SYMTAB; shdr->sh_flags = 0; shdr->sh_entsize = sizeof(Elf_Sym); - shdr->sh_link = 4; /* index of .strtab section */ + shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */ /* * setup symbols string table |