Issue 259 - crash when generating large .sym files with dump_syms on Linux. Patch by login_ing@yahoo.com, r=Liu Li
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@296 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
e055207058
commit
324d84c2f6
1 changed files with 56 additions and 34 deletions
|
@ -43,6 +43,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -75,6 +76,8 @@ struct LineInfo {
|
|||
int source_id;
|
||||
};
|
||||
|
||||
typedef std::list<struct LineInfo> LineInfoList;
|
||||
|
||||
// Information of a function.
|
||||
struct FuncInfo {
|
||||
// Name of the function.
|
||||
|
@ -93,9 +96,11 @@ struct FuncInfo {
|
|||
// Is there any lines included from other files?
|
||||
bool has_sol;
|
||||
// Line information array.
|
||||
std::vector<struct LineInfo> line_info;
|
||||
LineInfoList line_info;
|
||||
};
|
||||
|
||||
typedef std::list<struct FuncInfo> FuncInfoList;
|
||||
|
||||
// Information of a source file.
|
||||
struct SourceFileInfo {
|
||||
// Name string index into the string table.
|
||||
|
@ -107,13 +112,15 @@ struct SourceFileInfo {
|
|||
// Id of the source file.
|
||||
int source_id;
|
||||
// Functions information.
|
||||
std::vector<struct FuncInfo> func_info;
|
||||
FuncInfoList func_info;
|
||||
};
|
||||
|
||||
typedef std::list<struct SourceFileInfo> SourceFileInfoList;
|
||||
|
||||
// Information of a symbol table.
|
||||
// This is the root of all types of symbol.
|
||||
struct SymbolInfo {
|
||||
std::vector<struct SourceFileInfo> source_file_info;
|
||||
SourceFileInfoList source_file_info;
|
||||
|
||||
// The next source id for newly found source file.
|
||||
int next_source_id;
|
||||
|
@ -270,7 +277,6 @@ static int LoadFuncSymbols(struct nlist *list,
|
|||
struct nlist *cur_list = list;
|
||||
assert(cur_list->n_type == N_SO);
|
||||
++cur_list;
|
||||
|
||||
source_file_info->func_info.clear();
|
||||
while (cur_list < list_end) {
|
||||
// Go until the function symbol.
|
||||
|
@ -283,11 +289,15 @@ static int LoadFuncSymbols(struct nlist *list,
|
|||
}
|
||||
if (cur_list->n_type == N_FUN) {
|
||||
struct FuncInfo func_info;
|
||||
memset(&func_info, 0, sizeof(func_info));
|
||||
func_info.name =
|
||||
reinterpret_cast<char *>(cur_list->n_un.n_strx +
|
||||
stabstr_section->sh_offset);
|
||||
func_info.addr = cur_list->n_value;
|
||||
func_info.rva_to_base = 0;
|
||||
func_info.size = 0;
|
||||
func_info.stack_param_size = 0;
|
||||
func_info.has_sol = 0;
|
||||
|
||||
// Stack parameter size.
|
||||
cur_list += LoadStackParamSize(cur_list, list_end, &func_info);
|
||||
// Line info.
|
||||
|
@ -295,6 +305,7 @@ static int LoadFuncSymbols(struct nlist *list,
|
|||
list_end,
|
||||
*source_file_info,
|
||||
&func_info);
|
||||
|
||||
// Functions in this module should have address bigger than the module
|
||||
// startring address.
|
||||
// There maybe a lot of duplicated entry for a function in the symbol,
|
||||
|
@ -318,11 +329,12 @@ static bool CompareAddress(T1 *a, T2 *b) {
|
|||
// Return vector of pointers to the elements in the incoming array. So caller
|
||||
// should make sure the returned vector lives longer than the incoming vector.
|
||||
template<class T>
|
||||
static std::vector<T *> SortByAddress(std::vector<T> *array) {
|
||||
static std::vector<T *> SortByAddress(std::list<T> *array) {
|
||||
typedef typename std::list<T>::iterator It;
|
||||
std::vector<T *> sorted_array_ptr;
|
||||
sorted_array_ptr.reserve(array->size());
|
||||
for (size_t i = 0; i < array->size(); ++i)
|
||||
sorted_array_ptr.push_back(&(array->at(i)));
|
||||
for (It it = array -> begin(); it != array -> end(); it++)
|
||||
sorted_array_ptr.push_back(&(*it));
|
||||
std::sort(sorted_array_ptr.begin(),
|
||||
sorted_array_ptr.end(),
|
||||
std::ptr_fun(CompareAddress<T, T>));
|
||||
|
@ -366,10 +378,10 @@ static ElfW(Addr) NextAddress(
|
|||
}
|
||||
|
||||
static int FindFileByNameIdx(uint32_t name_index,
|
||||
const std::vector<SourceFileInfo> &files) {
|
||||
for (size_t i = 0; i < files.size(); ++i) {
|
||||
if (files[i].name_index == name_index)
|
||||
return files[i].source_id;
|
||||
SourceFileInfoList &files) {
|
||||
for (SourceFileInfoList::iterator it = files.begin(); it != files.end(); it++) {
|
||||
if (it->name_index == name_index)
|
||||
return it->source_id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -379,16 +391,20 @@ static int FindFileByNameIdx(uint32_t name_index,
|
|||
// Also fix the source id for the line info.
|
||||
static void AddIncludedFiles(struct SymbolInfo *symbols,
|
||||
const ElfW(Shdr) *stabstr_section) {
|
||||
size_t source_file_size = symbols->source_file_info.size();
|
||||
for (SourceFileInfoList::iterator source_file_it = symbols->source_file_info.begin();
|
||||
source_file_it != symbols->source_file_info.end();
|
||||
++source_file_it) {
|
||||
struct SourceFileInfo &source_file = *source_file_it;
|
||||
|
||||
for (size_t i = 0; i < source_file_size; ++i) {
|
||||
struct SourceFileInfo &source_file = symbols->source_file_info[i];
|
||||
for (FuncInfoList::iterator func_info_it = source_file.func_info.begin();
|
||||
func_info_it != source_file.func_info.end();
|
||||
++func_info_it) {
|
||||
struct FuncInfo &func_info = *func_info_it;
|
||||
|
||||
for (size_t j = 0; j < source_file.func_info.size(); ++j) {
|
||||
struct FuncInfo &func_info = source_file.func_info[j];
|
||||
for (LineInfoList::iterator line_info_it = func_info.line_info.begin();
|
||||
line_info_it != func_info.line_info.end(); ++line_info_it) {
|
||||
struct LineInfo &line_info = *line_info_it;
|
||||
|
||||
for (size_t k = 0; k < func_info.line_info.size(); ++k) {
|
||||
struct LineInfo &line_info = func_info.line_info[k];
|
||||
assert(line_info.source_name_index > 0);
|
||||
assert(source_file.name_index > 0);
|
||||
|
||||
|
@ -476,12 +492,15 @@ static bool ComputeSizeAndRVA(ElfW(Addr) loading_addr,
|
|||
func_info.size = kDefaultSize;
|
||||
}
|
||||
// Compute line size.
|
||||
for (size_t k = 0; k < func_info.line_info.size(); ++k) {
|
||||
struct LineInfo &line_info = func_info.line_info[k];
|
||||
for (LineInfoList::iterator line_info_it = func_info.line_info.begin();
|
||||
line_info_it != func_info.line_info.end(); line_info_it++) {
|
||||
struct LineInfo &line_info = *line_info_it;
|
||||
LineInfoList::iterator next_line_info_it = line_info_it;
|
||||
next_line_info_it++;
|
||||
line_info.size = 0;
|
||||
if (k + 1 < func_info.line_info.size()) {
|
||||
if (next_line_info_it != func_info.line_info.end()) {
|
||||
line_info.size =
|
||||
func_info.line_info[k + 1].rva_to_func - line_info.rva_to_func;
|
||||
next_line_info_it->rva_to_func - line_info.rva_to_func;
|
||||
} else {
|
||||
// The last line in the function.
|
||||
// If we can find a function or source file symbol immediately
|
||||
|
@ -605,11 +624,11 @@ static bool WriteModuleInfo(int fd,
|
|||
}
|
||||
|
||||
static bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) {
|
||||
for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
|
||||
if (symbols.source_file_info[i].source_id != -1) {
|
||||
const char *name = symbols.source_file_info[i].name;
|
||||
if (!WriteFormat(fd, "FILE %d %s\n",
|
||||
symbols.source_file_info[i].source_id, name))
|
||||
for (SourceFileInfoList::const_iterator it = symbols.source_file_info.begin();
|
||||
it != symbols.source_file_info.end(); it++) {
|
||||
if (it->source_id != -1) {
|
||||
const char *name = it->name;
|
||||
if (!WriteFormat(fd, "FILE %d %s\n", it->source_id, name))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -633,8 +652,9 @@ static bool WriteOneFunction(int fd,
|
|||
func_info.size,
|
||||
func_info.stack_param_size,
|
||||
func_name.c_str())) {
|
||||
for (size_t i = 0; i < func_info.line_info.size(); ++i) {
|
||||
const struct LineInfo &line_info = func_info.line_info[i];
|
||||
for (LineInfoList::const_iterator it = func_info.line_info.begin();
|
||||
it != func_info.line_info.end(); it++) {
|
||||
const struct LineInfo &line_info = *it;
|
||||
if (!WriteFormat(fd, "%lx %lx %d %d\n",
|
||||
line_info.rva_to_base,
|
||||
line_info.size,
|
||||
|
@ -648,10 +668,12 @@ static bool WriteOneFunction(int fd,
|
|||
}
|
||||
|
||||
static bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) {
|
||||
for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
|
||||
const struct SourceFileInfo &file_info = symbols.source_file_info[i];
|
||||
for (size_t j = 0; j < file_info.func_info.size(); ++j) {
|
||||
const struct FuncInfo &func_info = file_info.func_info[j];
|
||||
for (SourceFileInfoList::const_iterator it = symbols.source_file_info.begin();
|
||||
it != symbols.source_file_info.end(); it++) {
|
||||
const struct SourceFileInfo &file_info = *it;
|
||||
for (FuncInfoList::const_iterator fiIt = file_info.func_info.begin();
|
||||
fiIt != file_info.func_info.end(); fiIt++) {
|
||||
const struct FuncInfo &func_info = *fiIt;
|
||||
if (!WriteOneFunction(fd, func_info))
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue