X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Flttng-elf.cpp;fp=src%2Fcommon%2Flttng-elf.cpp;h=4fa711102ce5cd1a0f262cdcbeb395bebab52806;hp=e6b8624386914a38de270fbfbb5a45808d0fe6c1;hb=28ab034a2c3582d07d3423d2d746731f87d3969f;hpb=52e345b9ac912d033c2a2c25a170a01cf209839d diff --git a/src/common/lttng-elf.cpp b/src/common/lttng-elf.cpp index e6b862438..4fa711102 100644 --- a/src/common/lttng-elf.cpp +++ b/src/common/lttng-elf.cpp @@ -7,12 +7,14 @@ * */ -#include #include #include #include #include #include + +#include +#include #include #include #include @@ -22,18 +24,16 @@ #include #include -#include - -#define BUF_LEN 4096 -#define TEXT_SECTION_NAME ".text" -#define SYMBOL_TAB_SECTION_NAME ".symtab" -#define STRING_TAB_SECTION_NAME ".strtab" +#define BUF_LEN 4096 +#define TEXT_SECTION_NAME ".text" +#define SYMBOL_TAB_SECTION_NAME ".symtab" +#define STRING_TAB_SECTION_NAME ".strtab" #define DYNAMIC_SYMBOL_TAB_SECTION_NAME ".dynsym" #define DYNAMIC_STRING_TAB_SECTION_NAME ".dynstr" -#define NOTE_STAPSDT_SECTION_NAME ".note.stapsdt" -#define NOTE_STAPSDT_NAME "stapsdt" -#define NOTE_STAPSDT_TYPE 3 -#define MAX_SECTION_DATA_SIZE 512 * 1024 * 1024 +#define NOTE_STAPSDT_SECTION_NAME ".note.stapsdt" +#define NOTE_STAPSDT_NAME "stapsdt" +#define NOTE_STAPSDT_TYPE 3 +#define MAX_SECTION_DATA_SIZE 512 * 1024 * 1024 #if BYTE_ORDER == LITTLE_ENDIAN #define NATIVE_ELF_ENDIANNESS ELFDATA2LSB @@ -41,97 +41,97 @@ #define NATIVE_ELF_ENDIANNESS ELFDATA2MSB #endif -#define next_4bytes_boundary(x) (typeof(x)) ((((uint64_t)x) + 3) & ~0x03) - -#define bswap(x) \ - do { \ - switch (sizeof(x)) { \ - case 8: \ - x = be64toh((uint64_t)x); \ - break; \ - case 4: \ - x = be32toh((uint32_t)x); \ - break; \ - case 2: \ - x = be16toh((uint16_t)x); \ - break; \ - case 1: \ - break; \ - default: \ - abort(); \ - } \ +#define next_4bytes_boundary(x) (typeof(x)) ((((uint64_t) x) + 3) & ~0x03) + +#define bswap(x) \ + do { \ + switch (sizeof(x)) { \ + case 8: \ + x = be64toh((uint64_t) x); \ + break; \ + case 4: \ + x = be32toh((uint32_t) x); \ + break; \ + case 2: \ + x = be16toh((uint16_t) x); \ + break; \ + case 1: \ + break; \ + default: \ + abort(); \ + } \ } while (0) -#define bswap_shdr(shdr) \ - do { \ - bswap((shdr).sh_name); \ - bswap((shdr).sh_type); \ - bswap((shdr).sh_flags); \ - bswap((shdr).sh_addr); \ +#define bswap_shdr(shdr) \ + do { \ + bswap((shdr).sh_name); \ + bswap((shdr).sh_type); \ + bswap((shdr).sh_flags); \ + bswap((shdr).sh_addr); \ bswap((shdr).sh_offset); \ - bswap((shdr).sh_size); \ - bswap((shdr).sh_link); \ - bswap((shdr).sh_info); \ + bswap((shdr).sh_size); \ + bswap((shdr).sh_link); \ + bswap((shdr).sh_info); \ bswap((shdr).sh_addralign); \ bswap((shdr).sh_entsize); \ } while (0) -#define bswap_ehdr(ehdr) \ - do { \ - bswap((ehdr).e_type); \ - bswap((ehdr).e_machine); \ - bswap((ehdr).e_version); \ - bswap((ehdr).e_entry); \ - bswap((ehdr).e_phoff); \ - bswap((ehdr).e_shoff); \ - bswap((ehdr).e_flags); \ - bswap((ehdr).e_ehsize); \ - bswap((ehdr).e_phentsize); \ - bswap((ehdr).e_phnum); \ - bswap((ehdr).e_shentsize); \ - bswap((ehdr).e_shnum); \ - bswap((ehdr).e_shstrndx); \ +#define bswap_ehdr(ehdr) \ + do { \ + bswap((ehdr).e_type); \ + bswap((ehdr).e_machine); \ + bswap((ehdr).e_version); \ + bswap((ehdr).e_entry); \ + bswap((ehdr).e_phoff); \ + bswap((ehdr).e_shoff); \ + bswap((ehdr).e_flags); \ + bswap((ehdr).e_ehsize); \ + bswap((ehdr).e_phentsize); \ + bswap((ehdr).e_phnum); \ + bswap((ehdr).e_shentsize); \ + bswap((ehdr).e_shnum); \ + bswap((ehdr).e_shstrndx); \ } while (0) -#define copy_shdr(src_shdr, dst_shdr) \ - do { \ - (dst_shdr).sh_name = (src_shdr).sh_name; \ - (dst_shdr).sh_type = (src_shdr).sh_type; \ - (dst_shdr).sh_flags = (src_shdr).sh_flags; \ - (dst_shdr).sh_addr = (src_shdr).sh_addr; \ - (dst_shdr).sh_offset = (src_shdr).sh_offset; \ - (dst_shdr).sh_size = (src_shdr).sh_size; \ - (dst_shdr).sh_link = (src_shdr).sh_link; \ - (dst_shdr).sh_info = (src_shdr).sh_info; \ - (dst_shdr).sh_addralign = (src_shdr).sh_addralign; \ - (dst_shdr).sh_entsize = (src_shdr).sh_entsize; \ +#define copy_shdr(src_shdr, dst_shdr) \ + do { \ + (dst_shdr).sh_name = (src_shdr).sh_name; \ + (dst_shdr).sh_type = (src_shdr).sh_type; \ + (dst_shdr).sh_flags = (src_shdr).sh_flags; \ + (dst_shdr).sh_addr = (src_shdr).sh_addr; \ + (dst_shdr).sh_offset = (src_shdr).sh_offset; \ + (dst_shdr).sh_size = (src_shdr).sh_size; \ + (dst_shdr).sh_link = (src_shdr).sh_link; \ + (dst_shdr).sh_info = (src_shdr).sh_info; \ + (dst_shdr).sh_addralign = (src_shdr).sh_addralign; \ + (dst_shdr).sh_entsize = (src_shdr).sh_entsize; \ } while (0) -#define copy_ehdr(src_ehdr, dst_ehdr) \ - do { \ - (dst_ehdr).e_type = (src_ehdr).e_type; \ - (dst_ehdr).e_machine = (src_ehdr).e_machine; \ - (dst_ehdr).e_version = (src_ehdr).e_version; \ - (dst_ehdr).e_entry = (src_ehdr).e_entry; \ - (dst_ehdr).e_phoff = (src_ehdr).e_phoff; \ - (dst_ehdr).e_shoff = (src_ehdr).e_shoff; \ - (dst_ehdr).e_flags = (src_ehdr).e_flags; \ - (dst_ehdr).e_ehsize = (src_ehdr).e_ehsize; \ - (dst_ehdr).e_phentsize = (src_ehdr).e_phentsize; \ - (dst_ehdr).e_phnum = (src_ehdr).e_phnum; \ - (dst_ehdr).e_shentsize = (src_ehdr).e_shentsize; \ - (dst_ehdr).e_shnum = (src_ehdr).e_shnum; \ - (dst_ehdr).e_shstrndx = (src_ehdr).e_shstrndx; \ +#define copy_ehdr(src_ehdr, dst_ehdr) \ + do { \ + (dst_ehdr).e_type = (src_ehdr).e_type; \ + (dst_ehdr).e_machine = (src_ehdr).e_machine; \ + (dst_ehdr).e_version = (src_ehdr).e_version; \ + (dst_ehdr).e_entry = (src_ehdr).e_entry; \ + (dst_ehdr).e_phoff = (src_ehdr).e_phoff; \ + (dst_ehdr).e_shoff = (src_ehdr).e_shoff; \ + (dst_ehdr).e_flags = (src_ehdr).e_flags; \ + (dst_ehdr).e_ehsize = (src_ehdr).e_ehsize; \ + (dst_ehdr).e_phentsize = (src_ehdr).e_phentsize; \ + (dst_ehdr).e_phnum = (src_ehdr).e_phnum; \ + (dst_ehdr).e_shentsize = (src_ehdr).e_shentsize; \ + (dst_ehdr).e_shnum = (src_ehdr).e_shnum; \ + (dst_ehdr).e_shstrndx = (src_ehdr).e_shstrndx; \ } while (0) -#define copy_sym(src_sym, dst_sym) \ - do { \ - dst_sym.st_name = src_sym.st_name; \ - dst_sym.st_info = src_sym.st_info; \ - dst_sym.st_other = src_sym.st_other; \ - dst_sym.st_shndx = src_sym.st_shndx; \ - dst_sym.st_value = src_sym.st_value; \ - dst_sym.st_size = src_sym.st_size; \ +#define copy_sym(src_sym, dst_sym) \ + do { \ + dst_sym.st_name = src_sym.st_name; \ + dst_sym.st_info = src_sym.st_info; \ + dst_sym.st_other = src_sym.st_other; \ + dst_sym.st_shndx = src_sym.st_shndx; \ + dst_sym.st_value = src_sym.st_value; \ + dst_sym.st_size = src_sym.st_size; \ } while (0) #ifndef ELFCLASSNUM @@ -183,8 +183,8 @@ struct lttng_elf_shdr { */ struct lttng_elf_sym { uint32_t st_name; - uint8_t st_info; - uint8_t st_other; + uint8_t st_info; + uint8_t st_other; uint16_t st_shndx; uint64_t st_value; uint64_t st_size; @@ -203,28 +203,24 @@ struct lttng_elf { struct lttng_elf_ehdr *ehdr; }; -static inline -int is_elf_32_bit(struct lttng_elf *elf) +static inline int is_elf_32_bit(struct lttng_elf *elf) { return elf->bitness == ELFCLASS32; } -static inline -int is_elf_native_endian(struct lttng_elf *elf) +static inline int is_elf_native_endian(struct lttng_elf *elf) { return elf->endianness == NATIVE_ELF_ENDIANNESS; } -static -int populate_section_header(struct lttng_elf * elf, struct lttng_elf_shdr *shdr, - uint32_t index) +static int +populate_section_header(struct lttng_elf *elf, struct lttng_elf_shdr *shdr, uint32_t index) { int ret = 0; off_t offset; /* Compute the offset of the section in the file */ - offset = (off_t) elf->ehdr->e_shoff - + (off_t) index * elf->ehdr->e_shentsize; + offset = (off_t) elf->ehdr->e_shoff + (off_t) index * elf->ehdr->e_shentsize; if (lseek(elf->fd, offset, SEEK_SET) < 0) { PERROR("Error seeking to the beginning of ELF section header"); @@ -262,8 +258,7 @@ error: return ret; } -static -int populate_elf_header(struct lttng_elf *elf) +static int populate_elf_header(struct lttng_elf *elf) { int ret = 0; @@ -314,9 +309,8 @@ error: * * 0 is returned on succes, -1 on failure. */ -static -int lttng_elf_get_section_hdr(struct lttng_elf *elf, - uint16_t index, struct lttng_elf_shdr *out_header) +static int +lttng_elf_get_section_hdr(struct lttng_elf *elf, uint16_t index, struct lttng_elf_shdr *out_header) { int ret = 0; @@ -347,11 +341,10 @@ error: * * If no name is found, NULL is returned. */ -static -char *lttng_elf_get_section_name(struct lttng_elf *elf, off_t offset) +static char *lttng_elf_get_section_name(struct lttng_elf *elf, off_t offset) { char *name = NULL; - size_t name_length = 0, to_read; /* name_length does not include \0 */ + size_t name_length = 0, to_read; /* name_length does not include \0 */ if (!elf) { goto error; @@ -396,7 +389,7 @@ end: * We found the length of the section name, now seek back to the * beginning of the name and copy it in the newly allocated buffer. */ - name = calloc((name_length + 1)); /* + 1 for \0 */ + name = calloc((name_length + 1)); /* + 1 for \0 */ if (!name) { PERROR("Error allocating ELF section name buffer"); goto error; @@ -417,8 +410,7 @@ error: return NULL; } -static -int lttng_elf_validate_and_populate(struct lttng_elf *elf) +static int lttng_elf_validate_and_populate(struct lttng_elf *elf) { uint8_t version; uint8_t e_ident[EI_NIDENT]; @@ -528,8 +520,7 @@ end: * * Return a pointer to the instance on success, NULL on failure. */ -static -struct lttng_elf *lttng_elf_create(int fd) +static struct lttng_elf *lttng_elf_create(int fd) { struct lttng_elf_shdr section_names_shdr; struct lttng_elf *elf = NULL; @@ -568,8 +559,7 @@ struct lttng_elf *lttng_elf_create(int fd) goto error; } - ret = lttng_elf_get_section_hdr( - elf, elf->ehdr->e_shstrndx, §ion_names_shdr); + ret = lttng_elf_get_section_hdr(elf, elf->ehdr->e_shstrndx, §ion_names_shdr); if (ret) { goto error; } @@ -597,8 +587,7 @@ error: /* * Destroy the given lttng_elf instance. */ -static -void lttng_elf_destroy(struct lttng_elf *elf) +static void lttng_elf_destroy(struct lttng_elf *elf) { if (!elf) { return; @@ -612,22 +601,21 @@ void lttng_elf_destroy(struct lttng_elf *elf) free(elf); } -static -int lttng_elf_get_section_hdr_by_name(struct lttng_elf *elf, - const char *section_name, struct lttng_elf_shdr *section_hdr) +static int lttng_elf_get_section_hdr_by_name(struct lttng_elf *elf, + const char *section_name, + struct lttng_elf_shdr *section_hdr) { int i; char *curr_section_name; for (i = 0; i < elf->ehdr->e_shnum; ++i) { bool name_equal; - int ret = lttng_elf_get_section_hdr(elf, i, section_hdr); + int ret = lttng_elf_get_section_hdr(elf, i, section_hdr); if (ret) { break; } - curr_section_name = lttng_elf_get_section_name(elf, - section_hdr->sh_name); + curr_section_name = lttng_elf_get_section_name(elf, section_hdr->sh_name); if (!curr_section_name) { continue; } @@ -640,9 +628,7 @@ int lttng_elf_get_section_hdr_by_name(struct lttng_elf *elf, return LTTNG_ERR_ELF_PARSING; } -static -char *lttng_elf_get_section_data(struct lttng_elf *elf, - struct lttng_elf_shdr *shdr) +static char *lttng_elf_get_section_data(struct lttng_elf *elf, struct lttng_elf_shdr *shdr) { int ret; off_t section_offset; @@ -662,8 +648,7 @@ char *lttng_elf_get_section_data(struct lttng_elf *elf, } if (shdr->sh_size > max_alloc_size) { - ERR("ELF section size exceeds maximal allowed size of %zu bytes", - max_alloc_size); + ERR("ELF section size exceeds maximal allowed size of %zu bytes", max_alloc_size); goto error; } data = calloc(shdr->sh_size); @@ -692,9 +677,9 @@ error: * * Returns the offset on success or non-zero in case of failure. */ -static -int lttng_elf_convert_addr_in_text_to_offset(struct lttng_elf *elf_handle, - size_t addr, uint64_t *offset) +static int lttng_elf_convert_addr_in_text_to_offset(struct lttng_elf *elf_handle, + size_t addr, + uint64_t *offset) { int ret = 0; off_t text_section_offset; @@ -710,8 +695,7 @@ int lttng_elf_convert_addr_in_text_to_offset(struct lttng_elf *elf_handle, } /* Get a pointer to the .text section header. */ - ret = lttng_elf_get_section_hdr_by_name(elf_handle, - TEXT_SECTION_NAME, &text_section_hdr); + ret = lttng_elf_get_section_hdr_by_name(elf_handle, TEXT_SECTION_NAME, &text_section_hdr); if (ret) { DBG("Text section not found in binary."); ret = LTTNG_ERR_ELF_PARSING; @@ -720,16 +704,17 @@ int lttng_elf_convert_addr_in_text_to_offset(struct lttng_elf *elf_handle, text_section_offset = text_section_hdr.sh_offset; text_section_addr_beg = text_section_hdr.sh_addr; - text_section_addr_end = - text_section_addr_beg + text_section_hdr.sh_size; + text_section_addr_end = text_section_addr_beg + text_section_hdr.sh_size; /* * Verify that the address is within the .text section boundaries. */ if (addr < text_section_addr_beg || addr > text_section_addr_end) { DBG("Address found is outside of the .text section addr=0x%zx, " - ".text section=[0x%jd - 0x%jd].", addr, (intmax_t)text_section_addr_beg, - (intmax_t)text_section_addr_end); + ".text section=[0x%jd - 0x%jd].", + addr, + (intmax_t) text_section_addr_beg, + (intmax_t) text_section_addr_end); ret = LTTNG_ERR_ELF_PARSING; goto error; } @@ -767,7 +752,7 @@ int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset) struct lttng_elf_shdr strtab_hdr; struct lttng_elf *elf = NULL; - if (!symbol || !offset ) { + if (!symbol || !offset) { ret = LTTNG_ERR_ELF_PARSING; goto end; } @@ -784,13 +769,12 @@ int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset) * try to get the dynamic symbol table. All symbols in the dynamic * symbol tab are in the (normal) symbol table if it exists. */ - ret = lttng_elf_get_section_hdr_by_name(elf, SYMBOL_TAB_SECTION_NAME, - &symtab_hdr); + ret = lttng_elf_get_section_hdr_by_name(elf, SYMBOL_TAB_SECTION_NAME, &symtab_hdr); if (ret) { DBG("Cannot get ELF Symbol Table section. Trying to get ELF Dynamic Symbol Table section."); /* Get the dynamic symbol table section header. */ - ret = lttng_elf_get_section_hdr_by_name(elf, DYNAMIC_SYMBOL_TAB_SECTION_NAME, - &symtab_hdr); + ret = lttng_elf_get_section_hdr_by_name( + elf, DYNAMIC_SYMBOL_TAB_SECTION_NAME, &symtab_hdr); if (ret) { DBG("Cannot get ELF Symbol Table nor Dynamic Symbol Table sections."); ret = LTTNG_ERR_ELF_PARSING; @@ -810,8 +794,7 @@ int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset) } /* Get the string table section header. */ - ret = lttng_elf_get_section_hdr_by_name(elf, string_table_name, - &strtab_hdr); + ret = lttng_elf_get_section_hdr_by_name(elf, string_table_name, &strtab_hdr); if (ret) { DBG("Cannot get ELF string table section."); goto free_symbol_table_data; @@ -873,7 +856,7 @@ int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset) * Compare with the search symbol. If there is a match set the address * output parameter and return success. */ - if (strcmp(symbol, curr_sym_str) == 0 ) { + if (strcmp(symbol, curr_sym_str) == 0) { sym_found = 1; addr = curr_sym.st_value; break; @@ -896,7 +879,6 @@ int lttng_elf_get_symbol_offset(int fd, char *symbol, uint64_t *offset) goto free_string_table_data; } - free_string_table_data: free(string_table_data); free_symbol_table_data: @@ -915,8 +897,11 @@ end: * the SDT probes are. * On failure, returns -1. */ -int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name, - const char *probe_name, uint64_t **offsets, uint32_t *nb_probes) +int lttng_elf_get_sdt_probe_offsets(int fd, + const char *provider_name, + const char *probe_name, + uint64_t **offsets, + uint32_t *nb_probes) { int ret = 0, nb_match = 0; struct lttng_elf_shdr stap_note_section_hdr; @@ -942,16 +927,15 @@ int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name, } /* Get the stap note section header. */ - ret = lttng_elf_get_section_hdr_by_name(elf, NOTE_STAPSDT_SECTION_NAME, - &stap_note_section_hdr); + ret = lttng_elf_get_section_hdr_by_name( + elf, NOTE_STAPSDT_SECTION_NAME, &stap_note_section_hdr); if (ret) { DBG("Cannot get ELF stap note section."); goto destroy_elf_error; } /* Get the data associated with the stap note section. */ - stap_note_section_data = - lttng_elf_get_section_data(elf, &stap_note_section_hdr); + stap_note_section_data = lttng_elf_get_section_data(elf, &stap_note_section_hdr); if (stap_note_section_data == NULL) { DBG("Cannot get ELF stap note section data."); ret = LTTNG_ERR_ELF_PARSING; @@ -965,28 +949,26 @@ int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name, while (1) { curr_data_ptr = next_note_ptr; /* Check if we have reached the end of the note section. */ - if (curr_data_ptr >= - curr_note_section_begin + - stap_note_section_hdr.sh_size) { + if (curr_data_ptr >= curr_note_section_begin + stap_note_section_hdr.sh_size) { *nb_probes = nb_match; *offsets = probe_locs; ret = 0; break; } /* Get name size field. */ - name_size = next_4bytes_boundary(*(uint32_t*) curr_data_ptr); + name_size = next_4bytes_boundary(*(uint32_t *) curr_data_ptr); curr_data_ptr += sizeof(uint32_t); /* Sanity check; a zero name_size is reserved. */ if (name_size == 0) { DBG("Invalid name size field in SDT probe descriptions" - "section."); + "section."); ret = -1; goto realloc_error; } /* Get description size field. */ - desc_size = next_4bytes_boundary(*(uint32_t*) curr_data_ptr); + desc_size = next_4bytes_boundary(*(uint32_t *) curr_data_ptr); curr_data_ptr += sizeof(uint32_t); /* Get type field. */ @@ -1000,15 +982,14 @@ int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name, * name and the descriptor. To move to the next note, we move * the pointer according to those values. */ - next_note_ptr = next_note_ptr + - (3 * sizeof(uint32_t)) + desc_size + name_size; + next_note_ptr = next_note_ptr + (3 * sizeof(uint32_t)) + desc_size + name_size; /* * Move ptr to the end of the name string (we don't need it) * and go to the next 4 byte alignement. */ if (note_type != NOTE_STAPSDT_TYPE || - strncmp(curr_data_ptr, NOTE_STAPSDT_NAME, name_size) != 0) { + strncmp(curr_data_ptr, NOTE_STAPSDT_NAME, name_size) != 0) { continue; } @@ -1033,7 +1014,7 @@ int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name, /* Check if the provider and probe name match */ if (strcmp(provider_name, curr_provider) == 0 && - strcmp(probe_name, curr_probe) == 0) { + strcmp(probe_name, curr_probe) == 0) { int new_size; /* @@ -1066,8 +1047,8 @@ int lttng_elf_get_sdt_probe_offsets(int fd, const char *provider_name, * Use the virtual address of the probe to compute the offset of * this probe from the beginning of the executable file. */ - ret = lttng_elf_convert_addr_in_text_to_offset(elf, - curr_probe_location, &curr_probe_offset); + ret = lttng_elf_convert_addr_in_text_to_offset( + elf, curr_probe_location, &curr_probe_offset); if (ret) { DBG("Conversion error in SDT."); goto realloc_error;