Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: do not resolve debug info on build id mismatch #101

Open
wants to merge 2 commits into
base: stable-1.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/babeltrace/bin-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ struct bin_info {
int dwarf_fd;
/* Denotes whether the executable is position independent code. */
bool is_pic:1;
/* Denotes whether the build id in the trace matches to one on disk. */
bool file_build_id_matches:1;
/*
* Denotes whether the executable only has ELF symbols and no
* DWARF info.
Expand Down
266 changes: 235 additions & 31 deletions lib/bin-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
* character).
*/
#define ADDR_STR_LEN 20
#define BUILD_ID_NOTE_NAME "GNU"

BT_HIDDEN
int bin_info_init(void)
Expand Down Expand Up @@ -94,6 +95,9 @@ struct bin_info *bin_info_create(const char *path, uint64_t low_addr,
bin->memsz = memsz;
bin->low_addr = low_addr;
bin->high_addr = bin->low_addr + bin->memsz;
bin->build_id = NULL;
bin->build_id_len = 0;
bin->file_build_id_matches = false;

return bin;

Expand Down Expand Up @@ -124,37 +128,6 @@ void bin_info_destroy(struct bin_info *bin)
g_free(bin);
}


BT_HIDDEN
int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
size_t build_id_len)
{
if (!bin || !build_id) {
goto error;
}

bin->build_id = malloc(build_id_len);
if (!bin->build_id) {
goto error;
}

memcpy(bin->build_id, build_id, build_id_len);
bin->build_id_len = build_id_len;

/*
* Reset the is_elf_only flag in case it had been set
* previously, because we might find separate debug info using
* the new build id information.
*/
bin->is_elf_only = false;

return 0;

error:

return -1;
}

BT_HIDDEN
int bin_info_set_debug_link(struct bin_info *bin, char *filename, uint32_t crc)
{
Expand Down Expand Up @@ -687,6 +660,213 @@ int bin_info_get_nearest_symbol_from_section(Elf_Scn *scn, uint64_t addr,
g_free(_shdr);
return -1;
}
/**
* From a note section data buffer, check if it is a build id note.
*
* @param buf Pointer to a note section
*
* @returns 1 on match, 0 if `buf` does not contain a
* valid build id note
*/
static
int is_build_id_note_section(uint8_t *buf)
{
int ret = 0;
uint32_t name_sz, desc_sz, note_type;

/* The note section header has 3 32bit integer for the following:
* - Section name size
* - Description size
* - Note type
*/
name_sz = (uint32_t) *buf;
buf += sizeof(name_sz);

buf += sizeof(desc_sz);

note_type = (uint32_t) *buf;
buf += sizeof(note_type);

/* Check the note type. */
if (note_type != NT_GNU_BUILD_ID) {
goto invalid;
}

/* Check the note name. */
if (memcmp(buf, BUILD_ID_NOTE_NAME, name_sz) != 0) {
goto invalid;
}

ret = 1;

invalid:
return ret;
}

/**
* From a build id note section data buffer, check if the build id it contains
* is identical to the build id passed as parameter.
*
* @param file_build_id_note Pointer to the file build id note section.
* @param build_id Pointer to a build id to compare to.
* @param build_id_len length of the build id.
*
* @returns 1 on match, 0 otherwise.
*/
static
int compare_build_id_note_section(uint8_t *file_build_id_note, uint8_t *build_id, size_t build_id_len)
{
uint32_t name_sz, desc_sz, note_type;

/* The note section header has 3 32bit integer for the following:
* - Section name size
* - Description size
* - Note type
*/
name_sz = (uint32_t) *file_build_id_note;
file_build_id_note += sizeof(name_sz);
file_build_id_note += sizeof(desc_sz);
file_build_id_note += sizeof(note_type);

/*
* Move the pointer pass the name char array. This corresponds to the
* beginning of the description section. The description is the build
* id in the case of a build id note.
*/
file_build_id_note += name_sz;

/*
* Compare the binary build id with the supplied build id.
*/
if (memcmp(build_id, file_build_id_note, build_id_len) == 0) {
return 1;
}
return 0;
}

/**
* Checks if the build id stored in `bin` (bin->build_id) is matching the build
* id of the ondisk file (bin->elf_file).
*
* @param bin bin_info instance
* @param build_id build id to compare ot the on disk file
* @param build_id_len length of the build id
*
* @returns 1 on if the build id of stored in `bin` matches
* the build id of the ondisk file.
* 0 on if they are different or an error occured.
*/
static
int is_build_id_matching(struct bin_info *bin, uint8_t *build_id,
size_t build_id_len)
{
int ret, is_note_section, is_matching = 0;
Elf_Scn *curr_section = NULL, *next_section = NULL;
Elf_Data *note_data = NULL;
GElf_Shdr *curr_section_hdr = NULL;

if (!build_id) {
goto error;
}

/* Set ELF file if it hasn't been accessed yet. */
if (!bin->elf_file) {
ret = bin_info_set_elf_file(bin);
if (ret) {
/* Failed to set ELF file. */
goto error;
}
}

curr_section_hdr = g_new0(GElf_Shdr, 1);
if (!curr_section_hdr) {
goto error;
}

next_section = elf_nextscn(bin->elf_file, curr_section);
if (!next_section) {
goto error;
}

while (next_section) {
curr_section = next_section;
next_section = elf_nextscn(bin->elf_file, curr_section);

curr_section_hdr = gelf_getshdr(curr_section, curr_section_hdr);

if (!curr_section_hdr) {
goto error;
}

if (curr_section_hdr->sh_type != SHT_NOTE) {
continue;
}

note_data = elf_getdata(curr_section, NULL);
if (!note_data) {
goto error;
}

/* Check if the note is of the build-id type. */
is_note_section = is_build_id_note_section(note_data->d_buf);
if (!is_note_section)
{
continue;
}

/*
* Compare the build id of the on-disk file and
* the build id recorded in the trace.
*/
is_matching = compare_build_id_note_section(note_data->d_buf, build_id, build_id_len);
if (!is_matching) {
break;
}
}
error:
g_free(curr_section_hdr);
return is_matching;
}

BT_HIDDEN
int bin_info_set_build_id(struct bin_info *bin, uint8_t *build_id,
size_t build_id_len)
{
if (!bin || !build_id) {
goto error;
}

/*
* Check if the file found on the file system has the same build id
* that what was recorded in the trace.
*/
bin->file_build_id_matches = is_build_id_matching(bin, build_id, build_id_len);
if(!bin->file_build_id_matches) {
printf_verbose("Supplied Build ID does not match Build ID of the "
"binary or library found on the file system.");
goto error;
}

bin->build_id = malloc(build_id_len);
if (!bin->build_id) {
goto error;
}

memcpy(bin->build_id, build_id, build_id_len);
bin->build_id_len = (size_t) build_id_len;

/*
* Reset the is_elf_only flag in case it had been set
* previously, because we might find separate debug info using
* the new build id information.
*/
bin->is_elf_only = false;

return 0;

error:
return -1;
}

/**
* Get the name of the function containing a given address within an
Expand Down Expand Up @@ -918,6 +1098,14 @@ int bin_info_lookup_function_name(struct bin_info *bin, uint64_t addr,
goto error;
}

/*
* If the bin_info has a build id but it does not match the build id
* that was found on the file system, return an error.
*/
if (bin->build_id && !bin->file_build_id_matches) {
goto error;
}

/* Set DWARF info if it hasn't been accessed yet. */
if (!bin->dwarf_info && !bin->is_elf_only) {
ret = bin_info_set_dwarf_info(bin);
Expand Down Expand Up @@ -965,6 +1153,14 @@ int bin_info_get_bin_loc(struct bin_info *bin, uint64_t addr, char **bin_loc)
goto error;
}

/*
* If the bin_info has a build id but it does not match the build id
* that was found on the file system, return an error.
*/
if (bin->build_id && !bin->file_build_id_matches) {
goto error;
}

if (bin->is_pic) {
addr -= bin->low_addr;
ret = asprintf(&_bin_loc, "+%#0" PRIx64, addr);
Expand Down Expand Up @@ -1291,6 +1487,14 @@ int bin_info_lookup_source_location(struct bin_info *bin, uint64_t addr,
goto error;
}

/*
* If the bin_info has a build id but it does not match the build id
* that was found on the file system, return an error.
*/
if (bin->build_id && !bin->file_build_id_matches) {
goto error;
}

/* Set DWARF info if it hasn't been accessed yet. */
if (!bin->dwarf_info && !bin->is_elf_only) {
if (bin_info_set_dwarf_info(bin)) {
Expand Down
24 changes: 22 additions & 2 deletions lib/debug-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ struct debug_info_source *debug_info_source_create_from_bin(struct bin_info *bin
struct debug_info_source *debug_info_src = NULL;
struct source_location *src_loc = NULL;

/*
* If the build id of the binary or library does not match the one
* recorded on the trace, return NULL.
*/
if (bin->build_id && !bin->file_build_id_matches) {
goto end;
}

debug_info_src = g_new0(struct debug_info_source, 1);

if (!debug_info_src) {
Expand Down Expand Up @@ -271,6 +279,14 @@ struct debug_info_source *proc_debug_info_sources_get_entry(
{
struct bin_info *bin = value;

/*
* If the build ids in the trace and on the file don't match,
* skip it.
*/
if (!bin->file_build_id_matches) {
continue;
}

if (!bin_info_has_address(value, ip)) {
continue;
}
Expand Down Expand Up @@ -379,7 +395,7 @@ void handle_statedump_build_id_event(struct debug_info *debug_info,
struct bt_definition *build_id_def = NULL;
struct definition_sequence *build_id_seq;
struct bin_info *bin = NULL;
int i;
int i, ret;
int64_t vpid;
uint64_t baddr;
uint8_t *build_id = NULL;
Expand Down Expand Up @@ -455,7 +471,11 @@ void handle_statedump_build_id_event(struct debug_info *debug_info,
goto end;
}

bin_info_set_build_id(bin, build_id, build_id_len);
ret = bin_info_set_build_id(bin, build_id, build_id_len);
if (ret) {
printf_verbose("Failed to set build id: ret=%d", ret);
goto end;
}

end:
free(build_id);
Expand Down
Loading