aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorjimblandy@gmail.com <jimblandy@gmail.com@4c0a9323-5329-0410-9bdc-e9ce6186880e>2009-07-30 17:54:40 +0000
committerjimblandy@gmail.com <jimblandy@gmail.com@4c0a9323-5329-0410-9bdc-e9ce6186880e>2009-07-30 17:54:40 +0000
commit0d23e8c68659fa8c661e3e7454933234f90443c4 (patch)
treefa16adb611966f2234af41af0234d2f16942e603 /src/common
parentLinux dumper: Use pointers to SourceFileInfo structures. (diff)
downloadbreakpad-0d23e8c68659fa8c661e3e7454933234f90443c4.tar.xz
Linux dumper: Don't record file boundary addresses as null-name SourceFileInfoList entries.
STABS information introduces a compilation unit with an N_SO entry whose address is the start address of the file and whose string is the name of the compilation unit's main source file. However, STABS entries can only hold one address, so STABS indicates the compilation unit's ending address with an N_SO entry whose name is empty. Currently, the dumper's data structures simply create SourceFileInfo structures with empty names for these end-of-unit N_SO entries. We want to remove STABS-specific characteristics from these structures so that we can replace them with an input-format-independent structure. This moves end-of-compilation-unit addresses out of the symbol table structure, and into their own list of boundary addresses. a=jimblandy r=nealsid git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@369 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common')
-rw-r--r--src/common/linux/dump_symbols.cc52
1 files changed, 35 insertions, 17 deletions
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index e1c3047a..a52c13c8 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -131,6 +131,19 @@ class SourceFileInfoList : public std::list<SourceFileInfo *> {
struct SymbolInfo {
SourceFileInfoList source_file_info;
+ // An array of some addresses at which a file boundary occurs.
+ //
+ // The STABS information describing a compilation unit gives the
+ // unit's start address, but not its ending address or size. Those
+ // must be inferred by finding the start address of the next file.
+ // For the last compilation unit, or when one compilation unit ends
+ // before the next one starts, STABS includes an N_SO entry whose
+ // filename is the empty string; such an entry's address serves
+ // simply to mark the end of the preceding compilation unit. Rather
+ // than create FuncInfoList for such entries, we record their
+ // addresses here. These are not necessarily sorted.
+ std::vector<ElfW(Addr)> file_boundaries;
+
// The next source id for newly found source file.
int next_source_id;
};
@@ -390,11 +403,12 @@ static bool ComputeSizeAndRVA(ElfW(Addr) loading_addr,
FuncInfoList::iterator func_it;
LineInfoList::iterator line_it;
- // A table of all the addresses at which files and functions start.
- // We build this from our lists, sort it, and then use it to find
- // the ends of functions and source lines for which we have no size
+ // A table of all the addresses at which files and functions start
+ // or end. We build this from the file boundary list and our lists
+ // of files and functions, sort it, and then use it to find the ends
+ // of functions and source lines for which we have no size
// information.
- std::vector<ElfW(Addr)> boundaries;
+ std::vector<ElfW(Addr)> boundaries = symbols->file_boundaries;
for (file_it = symbols->source_file_info.begin();
file_it != symbols->source_file_info.end(); file_it++) {
boundaries.push_back((*file_it)->addr);
@@ -497,19 +511,23 @@ static bool LoadSymbols(const ElfW(Shdr) *stab_section,
int step = 1;
struct nlist *cur_list = lists + i;
if (cur_list->n_type == N_SO) {
- // FUNC <address> <length> <param_stack_size> <function>
- struct SourceFileInfo *source_file_info = new SourceFileInfo;
- source_file_info->name_index = cur_list->n_un.n_strx;
- source_file_info->name = reinterpret_cast<char *>(cur_list->n_un.n_strx +
- stabstr_section->sh_offset);
- source_file_info->addr = cur_list->n_value;
- if (strchr(source_file_info->name, '.'))
- source_file_info->source_id = symbols->next_source_id++;
- else
- source_file_info->source_id = -1;
- step = LoadFuncSymbols(cur_list, lists + nstab,
- stabstr_section, source_file_info);
- symbols->source_file_info.push_back(source_file_info);
+ if (cur_list->n_un.n_strx) {
+ struct SourceFileInfo *source_file_info = new SourceFileInfo;
+ source_file_info->name_index = cur_list->n_un.n_strx;
+ source_file_info->name = reinterpret_cast<char *>(cur_list->n_un.n_strx
+ + stabstr_section->sh_offset);
+ source_file_info->addr = cur_list->n_value;
+ if (strchr(source_file_info->name, '.'))
+ source_file_info->source_id = symbols->next_source_id++;
+ else
+ source_file_info->source_id = -1;
+ step = LoadFuncSymbols(cur_list, lists + nstab,
+ stabstr_section, source_file_info);
+ symbols->source_file_info.push_back(source_file_info);
+ } else {
+ // N_SO entries with no name mark file boundary addresses.
+ symbols->file_boundaries.push_back(cur_list->n_value);
+ }
}
i += step;
}