Bug 689184 part 1 - Keep ELF auxiliary vectors values within LinuxDumper. r=ted

This commit is contained in:
Mike Hommey 2012-07-25 07:43:22 +02:00
parent 9655afa272
commit 842cffefb4
3 changed files with 29 additions and 24 deletions

View File

@ -150,15 +150,20 @@ bool GetThreadRegisters(ThreadInfo* info) {
return true;
}
// All interesting auvx entry types are below AT_SYSINFO_EHDR
#define AT_MAX AT_SYSINFO_EHDR
LinuxDumper::LinuxDumper(int pid)
: pid_(pid),
threads_suspended_(false),
threads_(&allocator_, 8),
mappings_(&allocator_) {
mappings_(&allocator_),
auxv_(&allocator_, AT_MAX + 1) {
}
bool LinuxDumper::Init() {
return EnumerateThreads(&threads_) &&
return ReadAuxv() &&
EnumerateThreads(&threads_) &&
EnumerateMappings(&mappings_);
}
@ -271,34 +276,32 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
return success;
}
void*
LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const {
bool
LinuxDumper::ReadAuxv() {
char auxv_path[80];
BuildProcPath(auxv_path, pid, "auxv");
BuildProcPath(auxv_path, pid_, "auxv");
// If BuildProcPath errors out due to invalid input, we'll handle it when
// we try to sys_open the file.
// Find the AT_SYSINFO_EHDR entry for linux-gate.so
// See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
// information.
int fd = sys_open(auxv_path, O_RDONLY, 0);
if (fd < 0) {
return NULL;
return false;
}
elf_aux_entry one_aux_entry;
bool res = false;
while (sys_read(fd,
&one_aux_entry,
sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
one_aux_entry.a_type != AT_NULL) {
if (one_aux_entry.a_type == AT_SYSINFO_EHDR) {
close(fd);
return reinterpret_cast<void*>(one_aux_entry.a_un.a_val);
if (one_aux_entry.a_type <= AT_MAX) {
auxv_[one_aux_entry.a_type] = one_aux_entry.a_un.a_val;
res = true;
}
}
close(fd);
return NULL;
return res;
}
bool
@ -308,11 +311,13 @@ LinuxDumper::EnumerateMappings(wasteful_vector<MappingInfo*>* result) const {
// linux_gate_loc is the beginning of the kernel's mapping of
// linux-gate.so in the process. It doesn't actually show up in the
// maps list as a filename, so we use the aux vector to find it's
// load location and special case it's entry when creating the list
// of mappings.
// maps list as a filename, but it can be found using the AT_SYSINFO_EHDR
// aux vector entry, which gives the information necessary to special
// case its entry when creating the list of mappings.
// See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
// information.
const void* linux_gate_loc;
linux_gate_loc = FindBeginningOfLinuxGateSharedLibrary(pid_);
linux_gate_loc = reinterpret_cast<void *>(auxv_[AT_SYSINFO_EHDR]);
const int fd = sys_open(maps_path, O_RDONLY, 0);
if (fd < 0)

View File

@ -70,6 +70,9 @@ typedef struct
#elif defined(__x86_64__)
typedef Elf64_auxv_t elf_aux_entry;
#endif
typedef typeof(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
// When we find the VDSO mapping in the process's address space, this
// is the name we use for it when writing it to the minidump.
// This should always be less than NAME_MAX!
@ -145,6 +148,7 @@ class LinuxDumper {
const wasteful_vector<pid_t> &threads() { return threads_; }
const wasteful_vector<MappingInfo*> &mappings() { return mappings_; }
const MappingInfo* FindMapping(const void* address) const;
const wasteful_vector<elf_aux_val_t> &auxv() { return auxv_; }
// Find a block of memory to take as the stack given the top of stack pointer.
// stack: (output) the lowest address in the memory area
@ -167,13 +171,8 @@ class LinuxDumper {
bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
uint8_t identifier[sizeof(MDGUID)]);
// Utility method to find the location of where the kernel has
// mapped linux-gate.so in memory(shows up in /proc/pid/maps as
// [vdso], but we can't guarantee that it's the only virtual dynamic
// shared object. Parsing the auxilary vector for AT_SYSINFO_EHDR
// is the safest way to go.)
void* FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const;
private:
bool ReadAuxv();
bool EnumerateMappings(wasteful_vector<MappingInfo*>* result) const;
bool EnumerateThreads(wasteful_vector<pid_t>* result) const;
@ -184,6 +183,7 @@ class LinuxDumper {
bool threads_suspended_;
wasteful_vector<pid_t> threads_; // the ids of all the threads
wasteful_vector<MappingInfo*> mappings_; // info from /proc/<pid>/maps
wasteful_vector<elf_aux_val_t> auxv_; // info from /proc/<pid>/auxv
};
} // namespace google_breakpad

View File

@ -163,7 +163,7 @@ TEST(LinuxDumperTest, MappingsIncludeLinuxGate) {
LinuxDumper dumper(getpid());
ASSERT_TRUE(dumper.Init());
void* linux_gate_loc = dumper.FindBeginningOfLinuxGateSharedLibrary(getpid());
void* linux_gate_loc = reinterpret_cast<void *>(dumper.auxv()[AT_SYSINFO_EHDR]);
ASSERT_TRUE(linux_gate_loc);
bool found_linux_gate = false;