aboutsummaryrefslogtreecommitdiff
path: root/libutil++/bfd_support.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libutil++/bfd_support.cpp')
-rw-r--r--libutil++/bfd_support.cpp54
1 files changed, 46 insertions, 8 deletions
diff --git a/libutil++/bfd_support.cpp b/libutil++/bfd_support.cpp
index 4a83172..69d6938 100644
--- a/libutil++/bfd_support.cpp
+++ b/libutil++/bfd_support.cpp
@@ -20,7 +20,7 @@
#include <cstdlib>
#include <cstring>
-
+#include <cassert>
#include <iostream>
#include <fstream>
#include <sstream>
@@ -432,13 +432,28 @@ void bfd_info::close()
bfd_close(abfd);
}
+/**
+ * This function is only called when processing symbols retrieved from a
+ * debuginfo file that is separate from the actual runtime binary image.
+ * Separate debuginfo files may be needed in two different cases:
+ * 1) the real image is completely stripped, where there is no symbol
+ information at all
+ * 2) the real image has debuginfo stripped, and the user is requesting "-g"
+ * (src file/line num info)
+ * After all symbols are gathered up, there will be some filtering/removal of
+ * unnecessary symbols. In particular, the bfd_info::interesting_symbol()
+ * function filters out symbols whose section's flag value does not include
+ * SEC_LOAD. This filtering is required, so it must be retained. However,
+ * we run into a problem with symbols from debuginfo files, since the
+ * section flag does NOT include SEC_LOAD. To solve this problem, the
+ * translate_debuginfo_syms function maps the debuginfo symbol's sections to
+ * that of their corresponding real image.
+*/
void bfd_info::translate_debuginfo_syms(asymbol ** dbg_syms, long nr_dbg_syms)
{
- bfd_section ** image_sect;
unsigned int img_sect_cnt = 0;
bfd * image_bfd = image_bfd_info->abfd;
-
- image_sect = (bfd_section **) malloc(image_bfd->section_count * (sizeof(bfd_section *)));
+ multimap<string, bfd_section *> image_sections;
for (bfd_section * sect = image_bfd->sections;
sect && img_sect_cnt < image_bfd->section_count;
@@ -446,20 +461,43 @@ void bfd_info::translate_debuginfo_syms(asymbol ** dbg_syms, long nr_dbg_syms)
// A comment section marks the end of the needed sections
if (strstr(sect->name, ".comment") == sect->name)
break;
- image_sect[sect->index] = sect;
+ image_sections.insert(pair<string, bfd_section *>(sect->name, sect));
img_sect_cnt++;
}
asymbol * sym = dbg_syms[0];
+ string prev_sect_name = "";
+ bfd_section * matched_section = NULL;
for (int i = 0; i < nr_dbg_syms; sym = dbg_syms[++i]) {
+ bool section_switch;
+
+ if (strcmp(prev_sect_name.c_str(), sym->section->name)) {
+ section_switch = true;
+ prev_sect_name = sym->section->name;
+ } else {
+ section_switch = false;
+ }
if (sym->section->owner && sym->section->owner == abfd) {
- if ((unsigned int)sym->section->index < img_sect_cnt) {
- sym->section = image_sect[sym->section->index];
+ if (section_switch ) {
+ matched_section = NULL;
+ multimap<string, bfd_section *>::iterator it;
+ pair<multimap<string, bfd_section *>::iterator,
+ multimap<string, bfd_section *>::iterator> range;
+
+ range = image_sections.equal_range(sym->section->name);
+ for (it = range.first; it != range.second; it++) {
+ if ((*it).second->vma == sym->section->vma) {
+ matched_section = (*it).second;
+ break;
+ }
+ }
+ }
+ if (matched_section) {
+ sym->section = matched_section;
sym->the_bfd = image_bfd;
}
}
}
- free(image_sect);
}
#if SYNTHESIZE_SYMBOLS