aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluly81 <luly81@4c0a9323-5329-0410-9bdc-e9ce6186880e>2007-03-27 02:16:13 +0000
committerluly81 <luly81@4c0a9323-5329-0410-9bdc-e9ce6186880e>2007-03-27 02:16:13 +0000
commitab175ccc2be07e805973a399def35c885f1c49c9 (patch)
tree02bbff90a69f305b583dc3da233e37f5cd94a4dd
parentissue141: reviewer Waylonis (diff)
downloadbreakpad-ab175ccc2be07e805973a399def35c885f1c49c9.tar.xz
Fix bug of issue 135, now can dump symbols for dynamic libraries.
Also some minor fixes to make it compile with more strict compiling options. git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@133 4c0a9323-5329-0410-9bdc-e9ce6186880e
-rw-r--r--src/client/linux/handler/exception_handler_test.cc2
-rw-r--r--src/client/linux/handler/linux_thread.cc2
-rw-r--r--src/client/linux/handler/minidump_generator.cc24
-rw-r--r--src/common/linux/dump_symbols.cc53
-rw-r--r--src/common/string_conversion.cc4
5 files changed, 65 insertions, 20 deletions
diff --git a/src/client/linux/handler/exception_handler_test.cc b/src/client/linux/handler/exception_handler_test.cc
index 9c4a35a7..2d94553d 100644
--- a/src/client/linux/handler/exception_handler_test.cc
+++ b/src/client/linux/handler/exception_handler_test.cc
@@ -107,7 +107,7 @@ static bool MinidumpCallback(const char *dump_path,
}
int main(int argc, char *argv[]) {
- int handler_index = 1;
+ int handler_index = 0;
ExceptionHandler handler_ignore(".", NULL, MinidumpCallback,
(void*)handler_index, true);
++handler_index;
diff --git a/src/client/linux/handler/linux_thread.cc b/src/client/linux/handler/linux_thread.cc
index eeedec6e..1bd45b58 100644
--- a/src/client/linux/handler/linux_thread.cc
+++ b/src/client/linux/handler/linux_thread.cc
@@ -297,7 +297,7 @@ int LinuxThread::GetModuleCount() const {
int LinuxThread::ListModules(
CallbackParam<ModuleCallback> *callback_param) const {
char line[512];
- char *maps_path = "/proc/self/maps";
+ const char *maps_path = "/proc/self/maps";
int module_count = 0;
FILE *fp = fopen(maps_path, "r");
diff --git a/src/client/linux/handler/minidump_generator.cc b/src/client/linux/handler/minidump_generator.cc
index 3e4befc9..a7ba3e80 100644
--- a/src/client/linux/handler/minidump_generator.cc
+++ b/src/client/linux/handler/minidump_generator.cc
@@ -48,6 +48,10 @@
#include "google_breakpad/common/minidump_format.h"
#include "client/linux/handler/minidump_generator.h"
+#ifndef CLONE_UNTRACED
+#define CLONE_UNTRACED 0x00800000
+#endif
+
// This unnamed namespace contains helper functions.
namespace {
@@ -322,11 +326,11 @@ bool WriteThreadStream(MinidumpFileWriter *minidump_writer,
}
bool WriteCPUInformation(MDRawSystemInfo *sys_info) {
- char *proc_cpu_path = "/proc/cpuinfo";
+ const char *proc_cpu_path = "/proc/cpuinfo";
char line[128];
struct CpuInfoEntry {
- char *info_name;
+ const char *info_name;
int value;
} cpu_info_table[] = {
{ "processor", -1 },
@@ -384,7 +388,7 @@ bool WriteOSInformation(MinidumpFileWriter *minidump_writer,
char os_version[512];
size_t space_left = sizeof(os_version);
memset(os_version, 0, space_left);
- char *os_info_table[] = {
+ const char *os_info_table[] = {
uts.sysname,
uts.release,
uts.version,
@@ -392,7 +396,7 @@ bool WriteOSInformation(MinidumpFileWriter *minidump_writer,
"GNU/Linux",
NULL
};
- for (char **cur_os_info = os_info_table;
+ for (const char **cur_os_info = os_info_table;
*cur_os_info != NULL;
cur_os_info++) {
if (cur_os_info != os_info_table && space_left > 1) {
@@ -472,7 +476,8 @@ bool WriteThreadListStream(MinidumpFileWriter *minidump_writer,
context.thread_index = 0;
CallbackParam<ThreadCallback> callback_param(ThreadInfomationCallback,
&context);
- return thread_lister->ListThreads(&callback_param) == thread_count;
+ int written = thread_lister->ListThreads(&callback_param);
+ return written == thread_count;
}
bool WriteCVRecord(MinidumpFileWriter *minidump_writer,
@@ -481,7 +486,7 @@ bool WriteCVRecord(MinidumpFileWriter *minidump_writer,
TypedMDRVA<MDCVInfoPDB70> cv(minidump_writer);
// Only return the last path component of the full module path
- char *module_name = strrchr(module_path, '/');
+ const char *module_name = strrchr(module_path, '/');
// Increment past the slash
if (module_name)
++module_name;
@@ -491,11 +496,13 @@ bool WriteCVRecord(MinidumpFileWriter *minidump_writer,
size_t module_name_length = strlen(module_name);
if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t)))
return false;
- if (!cv.CopyIndexAfterObject(0, module_name, module_name_length))
+ if (!cv.CopyIndexAfterObject(0, const_cast<char *>(module_name),
+ module_name_length))
return false;
module->cv_record = cv.location();
MDCVInfoPDB70 *cv_ptr = cv.get();
+ memset(cv_ptr, 0, sizeof(MDCVInfoPDB70));
cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE;
cv_ptr->age = 0;
@@ -517,9 +524,8 @@ bool WriteCVRecord(MinidumpFileWriter *minidump_writer,
cv_ptr->signature.data4[5] = identifier[13];
cv_ptr->signature.data4[6] = identifier[14];
cv_ptr->signature.data4[7] = identifier[15];
- return true;
}
- return false;
+ return true;
}
struct ModuleInfoCallbackCtx {
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index a21b9114..0c4a2b32 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -138,15 +138,15 @@ void FixAddress(void *obj_base) {
}
// Find the prefered loading address of the binary.
-// It is the PT_LOAD segment with offset to zero.
ElfW(Addr) GetLoadingAddress(const ElfW(Phdr) *program_headers, int nheader) {
for (int i = 0; i < nheader; ++i) {
const ElfW(Phdr) &header = program_headers[i];
+ // For executable, it is the PT_LOAD segment with offset to zero.
if (header.p_type == PT_LOAD &&
header.p_offset == 0)
return header.p_vaddr;
}
- assert(!"Should get a valid loading address");
+ // For other types of ELF, return 0.
return 0;
}
@@ -263,6 +263,8 @@ int LoadFuncSymbols(struct nlist *list,
cur_list += LoadLineInfo(cur_list, list_end, &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,
+ // only one of them can met this.
if (func_info.addr >= source_file_info->addr) {
source_file_info->func_info.push_back(func_info);
}
@@ -344,10 +346,40 @@ bool ComputeSizeAndRVA(ElfW(Addr) loading_addr, struct SymbolInfo *symbols) {
ElfW(Addr) next_addr = NextAddress(&sorted_functions,
&sorted_files,
func_info);
- if (next_addr == 0)
- continue;
- func_info.size = next_addr - func_info.addr;
+ // I've noticed functions with an address bigger than any other functions
+ // and source files modules, this is probably the last function in the
+ // module, due to limitions of Linux stab symbol, it is impossible to get
+ // the exact size of this kind of function, thus we give it a default
+ // very big value. This should be safe since this is the last function.
+ // But it is a ugly hack.....
+ // The following code can reproduce the case:
+ // template<class T>
+ // void Foo(T value) {
+ // }
+ //
+ // int main(void) {
+ // Foo(10);
+ // Foo(std::string("hello"));
+ // return 0;
+ // }
+ // TODO(liuli): Find a better solution.
+ static const int kDefaultSize = 0x10000000;
+ static int no_next_addr_count = 0;
+ if (next_addr != 0) {
+ func_info.size = next_addr - func_info.addr;
+ } else {
+ if (no_next_addr_count > 1) {
+ fprintf(stderr, "Got more than one funtion without the \
+ following symbol. Igore this function.\n");
+ fprintf(stderr, "The dumped symbol may not correct.\n");
+ assert(!"This should not happen!\n");
+ func_info.size = 0;
+ continue;
+ }
+ no_next_addr_count++;
+ 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];
@@ -356,9 +388,18 @@ bool ComputeSizeAndRVA(ElfW(Addr) loading_addr, struct SymbolInfo *symbols) {
line_info.size =
func_info.line_info[k + 1].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
+ // following the line, we can get the size of the line by computing
+ // the difference of the next address to the starting address of this
+ // line.
+ // Otherwise, we need to set a default big enough value. This occurs
+ // mostly because the this function is the last one in the module.
if (next_addr != 0) {
ElfW(Off) next_addr_offset = next_addr - func_info.addr;
line_info.size = next_addr_offset - line_info.rva_to_func;
+ } else {
+ line_info.size = kDefaultSize;
}
}
line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base;
@@ -409,8 +450,6 @@ bool LoadSymbols(ElfW(Ehdr) *elf_header, struct SymbolInfo *symbols) {
ElfW(Addr) loading_addr = GetLoadingAddress(
reinterpret_cast<ElfW(Phdr) *>(elf_header->e_phoff),
elf_header->e_phnum);
- if (loading_addr == 0)
- return false;
const ElfW(Shdr) *sections =
reinterpret_cast<ElfW(Shdr) *>(elf_header->e_shoff);
diff --git a/src/common/string_conversion.cc b/src/common/string_conversion.cc
index b61b02fa..3e4d8e88 100644
--- a/src/common/string_conversion.cc
+++ b/src/common/string_conversion.cc
@@ -31,11 +31,11 @@
#include "processor/scoped_ptr.h"
#include "common/string_conversion.h"
+namespace google_breakpad {
+
using std::string;
using std::vector;
-namespace google_breakpad {
-
void UTF8ToUTF16(const char *in, vector<u_int16_t> *out) {
size_t source_length = strlen(in);
const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);