mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-01-11 06:15:29 +00:00
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
|
@ -43,6 +43,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -75,6 +76,8 @@ struct LineInfo {
|
||||||
int source_id;
|
int source_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::list<struct LineInfo> LineInfoList;
|
||||||
|
|
||||||
// Information of a function.
|
// Information of a function.
|
||||||
struct FuncInfo {
|
struct FuncInfo {
|
||||||
// Name of the function.
|
// Name of the function.
|
||||||
|
@ -93,9 +96,11 @@ struct FuncInfo {
|
||||||
// Is there any lines included from other files?
|
// Is there any lines included from other files?
|
||||||
bool has_sol;
|
bool has_sol;
|
||||||
// Line information array.
|
// Line information array.
|
||||||
std::vector<struct LineInfo> line_info;
|
LineInfoList line_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::list<struct FuncInfo> FuncInfoList;
|
||||||
|
|
||||||
// Information of a source file.
|
// Information of a source file.
|
||||||
struct SourceFileInfo {
|
struct SourceFileInfo {
|
||||||
// Name string index into the string table.
|
// Name string index into the string table.
|
||||||
|
@ -107,13 +112,15 @@ struct SourceFileInfo {
|
||||||
// Id of the source file.
|
// Id of the source file.
|
||||||
int source_id;
|
int source_id;
|
||||||
// Functions information.
|
// Functions information.
|
||||||
std::vector<struct FuncInfo> func_info;
|
FuncInfoList func_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::list<struct SourceFileInfo> SourceFileInfoList;
|
||||||
|
|
||||||
// Information of a symbol table.
|
// Information of a symbol table.
|
||||||
// This is the root of all types of symbol.
|
// This is the root of all types of symbol.
|
||||||
struct SymbolInfo {
|
struct SymbolInfo {
|
||||||
std::vector<struct SourceFileInfo> source_file_info;
|
SourceFileInfoList source_file_info;
|
||||||
|
|
||||||
// The next source id for newly found source file.
|
// The next source id for newly found source file.
|
||||||
int next_source_id;
|
int next_source_id;
|
||||||
|
@ -270,7 +277,6 @@ static int LoadFuncSymbols(struct nlist *list,
|
||||||
struct nlist *cur_list = list;
|
struct nlist *cur_list = list;
|
||||||
assert(cur_list->n_type == N_SO);
|
assert(cur_list->n_type == N_SO);
|
||||||
++cur_list;
|
++cur_list;
|
||||||
|
|
||||||
source_file_info->func_info.clear();
|
source_file_info->func_info.clear();
|
||||||
while (cur_list < list_end) {
|
while (cur_list < list_end) {
|
||||||
// Go until the function symbol.
|
// Go until the function symbol.
|
||||||
|
@ -283,11 +289,15 @@ static int LoadFuncSymbols(struct nlist *list,
|
||||||
}
|
}
|
||||||
if (cur_list->n_type == N_FUN) {
|
if (cur_list->n_type == N_FUN) {
|
||||||
struct FuncInfo func_info;
|
struct FuncInfo func_info;
|
||||||
memset(&func_info, 0, sizeof(func_info));
|
|
||||||
func_info.name =
|
func_info.name =
|
||||||
reinterpret_cast<char *>(cur_list->n_un.n_strx +
|
reinterpret_cast<char *>(cur_list->n_un.n_strx +
|
||||||
stabstr_section->sh_offset);
|
stabstr_section->sh_offset);
|
||||||
func_info.addr = cur_list->n_value;
|
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.
|
// Stack parameter size.
|
||||||
cur_list += LoadStackParamSize(cur_list, list_end, &func_info);
|
cur_list += LoadStackParamSize(cur_list, list_end, &func_info);
|
||||||
// Line info.
|
// Line info.
|
||||||
|
@ -295,6 +305,7 @@ static int LoadFuncSymbols(struct nlist *list,
|
||||||
list_end,
|
list_end,
|
||||||
*source_file_info,
|
*source_file_info,
|
||||||
&func_info);
|
&func_info);
|
||||||
|
|
||||||
// Functions in this module should have address bigger than the module
|
// Functions in this module should have address bigger than the module
|
||||||
// startring address.
|
// startring address.
|
||||||
// There maybe a lot of duplicated entry for a function in the symbol,
|
// 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
|
// 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.
|
// should make sure the returned vector lives longer than the incoming vector.
|
||||||
template<class T>
|
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;
|
std::vector<T *> sorted_array_ptr;
|
||||||
sorted_array_ptr.reserve(array->size());
|
sorted_array_ptr.reserve(array->size());
|
||||||
for (size_t i = 0; i < array->size(); ++i)
|
for (It it = array -> begin(); it != array -> end(); it++)
|
||||||
sorted_array_ptr.push_back(&(array->at(i)));
|
sorted_array_ptr.push_back(&(*it));
|
||||||
std::sort(sorted_array_ptr.begin(),
|
std::sort(sorted_array_ptr.begin(),
|
||||||
sorted_array_ptr.end(),
|
sorted_array_ptr.end(),
|
||||||
std::ptr_fun(CompareAddress<T, T>));
|
std::ptr_fun(CompareAddress<T, T>));
|
||||||
|
@ -366,10 +378,10 @@ static ElfW(Addr) NextAddress(
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FindFileByNameIdx(uint32_t name_index,
|
static int FindFileByNameIdx(uint32_t name_index,
|
||||||
const std::vector<SourceFileInfo> &files) {
|
SourceFileInfoList &files) {
|
||||||
for (size_t i = 0; i < files.size(); ++i) {
|
for (SourceFileInfoList::iterator it = files.begin(); it != files.end(); it++) {
|
||||||
if (files[i].name_index == name_index)
|
if (it->name_index == name_index)
|
||||||
return files[i].source_id;
|
return it->source_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -379,16 +391,20 @@ static int FindFileByNameIdx(uint32_t name_index,
|
||||||
// Also fix the source id for the line info.
|
// Also fix the source id for the line info.
|
||||||
static void AddIncludedFiles(struct SymbolInfo *symbols,
|
static void AddIncludedFiles(struct SymbolInfo *symbols,
|
||||||
const ElfW(Shdr) *stabstr_section) {
|
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) {
|
for (FuncInfoList::iterator func_info_it = source_file.func_info.begin();
|
||||||
struct SourceFileInfo &source_file = symbols->source_file_info[i];
|
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) {
|
for (LineInfoList::iterator line_info_it = func_info.line_info.begin();
|
||||||
struct FuncInfo &func_info = source_file.func_info[j];
|
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(line_info.source_name_index > 0);
|
||||||
assert(source_file.name_index > 0);
|
assert(source_file.name_index > 0);
|
||||||
|
|
||||||
|
@ -476,12 +492,15 @@ static bool ComputeSizeAndRVA(ElfW(Addr) loading_addr,
|
||||||
func_info.size = kDefaultSize;
|
func_info.size = kDefaultSize;
|
||||||
}
|
}
|
||||||
// Compute line size.
|
// Compute line size.
|
||||||
for (size_t k = 0; k < func_info.line_info.size(); ++k) {
|
for (LineInfoList::iterator line_info_it = func_info.line_info.begin();
|
||||||
struct LineInfo &line_info = func_info.line_info[k];
|
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;
|
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 =
|
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 {
|
} else {
|
||||||
// The last line in the function.
|
// The last line in the function.
|
||||||
// If we can find a function or source file symbol immediately
|
// 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) {
|
static bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) {
|
||||||
for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
|
for (SourceFileInfoList::const_iterator it = symbols.source_file_info.begin();
|
||||||
if (symbols.source_file_info[i].source_id != -1) {
|
it != symbols.source_file_info.end(); it++) {
|
||||||
const char *name = symbols.source_file_info[i].name;
|
if (it->source_id != -1) {
|
||||||
if (!WriteFormat(fd, "FILE %d %s\n",
|
const char *name = it->name;
|
||||||
symbols.source_file_info[i].source_id, name))
|
if (!WriteFormat(fd, "FILE %d %s\n", it->source_id, name))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -633,8 +652,9 @@ static bool WriteOneFunction(int fd,
|
||||||
func_info.size,
|
func_info.size,
|
||||||
func_info.stack_param_size,
|
func_info.stack_param_size,
|
||||||
func_name.c_str())) {
|
func_name.c_str())) {
|
||||||
for (size_t i = 0; i < func_info.line_info.size(); ++i) {
|
for (LineInfoList::const_iterator it = func_info.line_info.begin();
|
||||||
const struct LineInfo &line_info = func_info.line_info[i];
|
it != func_info.line_info.end(); it++) {
|
||||||
|
const struct LineInfo &line_info = *it;
|
||||||
if (!WriteFormat(fd, "%lx %lx %d %d\n",
|
if (!WriteFormat(fd, "%lx %lx %d %d\n",
|
||||||
line_info.rva_to_base,
|
line_info.rva_to_base,
|
||||||
line_info.size,
|
line_info.size,
|
||||||
|
@ -648,10 +668,12 @@ static bool WriteOneFunction(int fd,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) {
|
static bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) {
|
||||||
for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
|
for (SourceFileInfoList::const_iterator it = symbols.source_file_info.begin();
|
||||||
const struct SourceFileInfo &file_info = symbols.source_file_info[i];
|
it != symbols.source_file_info.end(); it++) {
|
||||||
for (size_t j = 0; j < file_info.func_info.size(); ++j) {
|
const struct SourceFileInfo &file_info = *it;
|
||||||
const struct FuncInfo &func_info = file_info.func_info[j];
|
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))
|
if (!WriteOneFunction(fd, func_info))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue