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:
ted.mielczarek 2008-11-24 20:47:37 +00:00
parent e055207058
commit 324d84c2f6

View file

@ -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;
}