xref: /aosp_15_r20/external/google-breakpad/src/common/solaris/dump_symbols.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2010 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle // Author: Alfred Peng
30*9712c20fSFrederick Mayle 
31*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
32*9712c20fSFrederick Mayle #include <config.h>  // Must come first
33*9712c20fSFrederick Mayle #endif
34*9712c20fSFrederick Mayle 
35*9712c20fSFrederick Mayle #include <demangle.h>
36*9712c20fSFrederick Mayle #include <fcntl.h>
37*9712c20fSFrederick Mayle #include <gelf.h>
38*9712c20fSFrederick Mayle #include <link.h>
39*9712c20fSFrederick Mayle #include <sys/mman.h>
40*9712c20fSFrederick Mayle #include <stab.h>
41*9712c20fSFrederick Mayle #include <sys/stat.h>
42*9712c20fSFrederick Mayle #include <sys/types.h>
43*9712c20fSFrederick Mayle #include <unistd.h>
44*9712c20fSFrederick Mayle 
45*9712c20fSFrederick Mayle #include <functional>
46*9712c20fSFrederick Mayle #include <map>
47*9712c20fSFrederick Mayle #include <vector>
48*9712c20fSFrederick Mayle 
49*9712c20fSFrederick Mayle #include "common/scoped_ptr.h"
50*9712c20fSFrederick Mayle #include "common/solaris/dump_symbols.h"
51*9712c20fSFrederick Mayle #include "common/solaris/file_id.h"
52*9712c20fSFrederick Mayle #include "common/solaris/guid_creator.h"
53*9712c20fSFrederick Mayle 
54*9712c20fSFrederick Mayle // This namespace contains helper functions.
55*9712c20fSFrederick Mayle namespace {
56*9712c20fSFrederick Mayle 
57*9712c20fSFrederick Mayle using std::make_pair;
58*9712c20fSFrederick Mayle 
59*9712c20fSFrederick Mayle #if defined(_LP64)
60*9712c20fSFrederick Mayle typedef Elf64_Sym   Elf_Sym;
61*9712c20fSFrederick Mayle #else
62*9712c20fSFrederick Mayle typedef Elf32_Sym   Elf_Sym;
63*9712c20fSFrederick Mayle #endif
64*9712c20fSFrederick Mayle 
65*9712c20fSFrederick Mayle // Symbol table entry from stabs. Sun CC specific.
66*9712c20fSFrederick Mayle struct slist {
67*9712c20fSFrederick Mayle   // String table index.
68*9712c20fSFrederick Mayle   unsigned int n_strx;
69*9712c20fSFrederick Mayle   // Stab type.
70*9712c20fSFrederick Mayle   unsigned char n_type;
71*9712c20fSFrederick Mayle   char n_other;
72*9712c20fSFrederick Mayle   short n_desc;
73*9712c20fSFrederick Mayle   unsigned long n_value;
74*9712c20fSFrederick Mayle };
75*9712c20fSFrederick Mayle 
76*9712c20fSFrederick Mayle // Symbol table entry
77*9712c20fSFrederick Mayle struct SymbolEntry {
78*9712c20fSFrederick Mayle   // Offset from the start of the file.
79*9712c20fSFrederick Mayle   GElf_Addr offset;
80*9712c20fSFrederick Mayle   // Function size.
81*9712c20fSFrederick Mayle   GElf_Word size;
82*9712c20fSFrederick Mayle };
83*9712c20fSFrederick Mayle 
84*9712c20fSFrederick Mayle // Infomation of a line.
85*9712c20fSFrederick Mayle struct LineInfo {
86*9712c20fSFrederick Mayle   // Offset from start of the function.
87*9712c20fSFrederick Mayle   // Load from stab symbol.
88*9712c20fSFrederick Mayle   GElf_Off rva_to_func;
89*9712c20fSFrederick Mayle   // Offset from base of the loading binary.
90*9712c20fSFrederick Mayle   GElf_Off rva_to_base;
91*9712c20fSFrederick Mayle   // Size of the line.
92*9712c20fSFrederick Mayle   // The first line: equals to rva_to_func.
93*9712c20fSFrederick Mayle   // The other lines: the difference of rva_to_func of the line and
94*9712c20fSFrederick Mayle   // rva_to_func of the previous N_SLINE.
95*9712c20fSFrederick Mayle   uint32_t size;
96*9712c20fSFrederick Mayle   // Line number.
97*9712c20fSFrederick Mayle   uint32_t line_num;
98*9712c20fSFrederick Mayle };
99*9712c20fSFrederick Mayle 
100*9712c20fSFrederick Mayle // Information of a function.
101*9712c20fSFrederick Mayle struct FuncInfo {
102*9712c20fSFrederick Mayle   // Name of the function.
103*9712c20fSFrederick Mayle   const char* name;
104*9712c20fSFrederick Mayle   // Offset from the base of the loading address.
105*9712c20fSFrederick Mayle   GElf_Off rva_to_base;
106*9712c20fSFrederick Mayle   // Virtual address of the function.
107*9712c20fSFrederick Mayle   // Load from stab symbol.
108*9712c20fSFrederick Mayle   GElf_Addr addr;
109*9712c20fSFrederick Mayle   // Size of the function.
110*9712c20fSFrederick Mayle   // Equal to rva_to_func of the last function line.
111*9712c20fSFrederick Mayle   uint32_t size;
112*9712c20fSFrederick Mayle   // Total size of stack parameters.
113*9712c20fSFrederick Mayle   uint32_t stack_param_size;
114*9712c20fSFrederick Mayle   // Line information array.
115*9712c20fSFrederick Mayle   std::vector<struct LineInfo> line_info;
116*9712c20fSFrederick Mayle };
117*9712c20fSFrederick Mayle 
118*9712c20fSFrederick Mayle // Information of a source file.
119*9712c20fSFrederick Mayle struct SourceFileInfo {
120*9712c20fSFrederick Mayle   // Name of the source file.
121*9712c20fSFrederick Mayle   const char* name;
122*9712c20fSFrederick Mayle   // Starting address of the source file.
123*9712c20fSFrederick Mayle   GElf_Addr addr;
124*9712c20fSFrederick Mayle   // Id of the source file.
125*9712c20fSFrederick Mayle   int source_id;
126*9712c20fSFrederick Mayle   // Functions information.
127*9712c20fSFrederick Mayle   std::vector<struct FuncInfo> func_info;
128*9712c20fSFrederick Mayle };
129*9712c20fSFrederick Mayle 
130*9712c20fSFrederick Mayle struct CompareString {
operator ()__anon494f73470111::CompareString131*9712c20fSFrederick Mayle   bool operator()(const char* s1, const char* s2) const {
132*9712c20fSFrederick Mayle     return strcmp(s1, s2) < 0;
133*9712c20fSFrederick Mayle   }
134*9712c20fSFrederick Mayle };
135*9712c20fSFrederick Mayle 
136*9712c20fSFrederick Mayle typedef std::map<const char*, struct SymbolEntry*, CompareString> SymbolMap;
137*9712c20fSFrederick Mayle 
138*9712c20fSFrederick Mayle // Information of a symbol table.
139*9712c20fSFrederick Mayle // This is the root of all types of symbol.
140*9712c20fSFrederick Mayle struct SymbolInfo {
141*9712c20fSFrederick Mayle   std::vector<struct SourceFileInfo> source_file_info;
142*9712c20fSFrederick Mayle   // Symbols information.
143*9712c20fSFrederick Mayle   SymbolMap symbol_entries;
144*9712c20fSFrederick Mayle };
145*9712c20fSFrederick Mayle 
146*9712c20fSFrederick Mayle // Stab section name.
147*9712c20fSFrederick Mayle const char* kStabName = ".stab";
148*9712c20fSFrederick Mayle 
149*9712c20fSFrederick Mayle // Stab str section name.
150*9712c20fSFrederick Mayle const char* kStabStrName = ".stabstr";
151*9712c20fSFrederick Mayle 
152*9712c20fSFrederick Mayle // Symtab section name.
153*9712c20fSFrederick Mayle const char* kSymtabName = ".symtab";
154*9712c20fSFrederick Mayle 
155*9712c20fSFrederick Mayle // Strtab section name.
156*9712c20fSFrederick Mayle const char* kStrtabName = ".strtab";
157*9712c20fSFrederick Mayle 
158*9712c20fSFrederick Mayle // Default buffer lenght for demangle.
159*9712c20fSFrederick Mayle const int demangleLen = 20000;
160*9712c20fSFrederick Mayle 
161*9712c20fSFrederick Mayle // Offset to the string table.
162*9712c20fSFrederick Mayle uint64_t stringOffset = 0;
163*9712c20fSFrederick Mayle 
164*9712c20fSFrederick Mayle // Update the offset to the start of the string index of the next
165*9712c20fSFrederick Mayle // object module for every N_ENDM stabs.
RecalculateOffset(struct slist * cur_list,char * stabstr)166*9712c20fSFrederick Mayle inline void RecalculateOffset(struct slist* cur_list, char* stabstr) {
167*9712c20fSFrederick Mayle   while ((--cur_list)->n_strx == 0) ;
168*9712c20fSFrederick Mayle   stringOffset += cur_list->n_strx;
169*9712c20fSFrederick Mayle 
170*9712c20fSFrederick Mayle   char* temp = stabstr + stringOffset;
171*9712c20fSFrederick Mayle   while (*temp != '\0') {
172*9712c20fSFrederick Mayle     ++stringOffset;
173*9712c20fSFrederick Mayle     ++temp;
174*9712c20fSFrederick Mayle   }
175*9712c20fSFrederick Mayle   // Skip the extra '\0'
176*9712c20fSFrederick Mayle   ++stringOffset;
177*9712c20fSFrederick Mayle }
178*9712c20fSFrederick Mayle 
179*9712c20fSFrederick Mayle // Demangle using demangle library on Solaris.
Demangle(const char * mangled)180*9712c20fSFrederick Mayle std::string Demangle(const char* mangled) {
181*9712c20fSFrederick Mayle   int status = 0;
182*9712c20fSFrederick Mayle   std::string str(mangled);
183*9712c20fSFrederick Mayle   char* demangled = (char*)malloc(demangleLen);
184*9712c20fSFrederick Mayle 
185*9712c20fSFrederick Mayle   if (!demangled) {
186*9712c20fSFrederick Mayle     fprintf(stderr, "no enough memory.\n");
187*9712c20fSFrederick Mayle     goto out;
188*9712c20fSFrederick Mayle   }
189*9712c20fSFrederick Mayle 
190*9712c20fSFrederick Mayle   if ((status = cplus_demangle(mangled, demangled, demangleLen)) ==
191*9712c20fSFrederick Mayle       DEMANGLE_ESPACE) {
192*9712c20fSFrederick Mayle     fprintf(stderr, "incorrect demangle.\n");
193*9712c20fSFrederick Mayle     goto out;
194*9712c20fSFrederick Mayle   }
195*9712c20fSFrederick Mayle 
196*9712c20fSFrederick Mayle   str = demangled;
197*9712c20fSFrederick Mayle   free(demangled);
198*9712c20fSFrederick Mayle 
199*9712c20fSFrederick Mayle out:
200*9712c20fSFrederick Mayle   return str;
201*9712c20fSFrederick Mayle }
202*9712c20fSFrederick Mayle 
WriteFormat(int fd,const char * fmt,...)203*9712c20fSFrederick Mayle bool WriteFormat(int fd, const char* fmt, ...) {
204*9712c20fSFrederick Mayle   va_list list;
205*9712c20fSFrederick Mayle   char buffer[4096];
206*9712c20fSFrederick Mayle   ssize_t expected, written;
207*9712c20fSFrederick Mayle   va_start(list, fmt);
208*9712c20fSFrederick Mayle   vsnprintf(buffer, sizeof(buffer), fmt, list);
209*9712c20fSFrederick Mayle   expected = strlen(buffer);
210*9712c20fSFrederick Mayle   written = write(fd, buffer, strlen(buffer));
211*9712c20fSFrederick Mayle   va_end(list);
212*9712c20fSFrederick Mayle   return expected == written;
213*9712c20fSFrederick Mayle }
214*9712c20fSFrederick Mayle 
IsValidElf(const GElf_Ehdr * elf_header)215*9712c20fSFrederick Mayle bool IsValidElf(const GElf_Ehdr* elf_header) {
216*9712c20fSFrederick Mayle   return memcmp(elf_header, ELFMAG, SELFMAG) == 0;
217*9712c20fSFrederick Mayle }
218*9712c20fSFrederick Mayle 
FindSectionByName(Elf * elf,const char * name,int shstrndx,GElf_Shdr * shdr)219*9712c20fSFrederick Mayle static bool FindSectionByName(Elf* elf, const char* name,
220*9712c20fSFrederick Mayle                               int shstrndx,
221*9712c20fSFrederick Mayle                               GElf_Shdr* shdr) {
222*9712c20fSFrederick Mayle   assert(name != NULL);
223*9712c20fSFrederick Mayle 
224*9712c20fSFrederick Mayle   if (strlen(name) == 0)
225*9712c20fSFrederick Mayle     return false;
226*9712c20fSFrederick Mayle 
227*9712c20fSFrederick Mayle   Elf_Scn* scn = NULL;
228*9712c20fSFrederick Mayle 
229*9712c20fSFrederick Mayle   while ((scn = elf_nextscn(elf, scn)) != NULL) {
230*9712c20fSFrederick Mayle     if (gelf_getshdr(scn, shdr) == (GElf_Shdr*)0) {
231*9712c20fSFrederick Mayle       fprintf(stderr, "failed to read section header: %s\n", elf_errmsg(0));
232*9712c20fSFrederick Mayle       return false;
233*9712c20fSFrederick Mayle     }
234*9712c20fSFrederick Mayle 
235*9712c20fSFrederick Mayle     const char* section_name = elf_strptr(elf, shstrndx, shdr->sh_name);
236*9712c20fSFrederick Mayle     if (!section_name) {
237*9712c20fSFrederick Mayle       fprintf(stderr, "Section name error: %s\n", elf_errmsg(-1));
238*9712c20fSFrederick Mayle       continue;
239*9712c20fSFrederick Mayle     }
240*9712c20fSFrederick Mayle 
241*9712c20fSFrederick Mayle     if (strcmp(section_name, name) == 0)
242*9712c20fSFrederick Mayle       return true;
243*9712c20fSFrederick Mayle   }
244*9712c20fSFrederick Mayle 
245*9712c20fSFrederick Mayle   return false;
246*9712c20fSFrederick Mayle }
247*9712c20fSFrederick Mayle 
248*9712c20fSFrederick Mayle // The parameter size is used for FPO-optimized code, and
249*9712c20fSFrederick Mayle // this is all tied up with the debugging data for Windows x86.
250*9712c20fSFrederick Mayle // Set it to 0 on Solaris.
LoadStackParamSize(struct slist * list,struct slist * list_end,struct FuncInfo * func_info)251*9712c20fSFrederick Mayle int LoadStackParamSize(struct slist* list,
252*9712c20fSFrederick Mayle                        struct slist* list_end,
253*9712c20fSFrederick Mayle                        struct FuncInfo* func_info) {
254*9712c20fSFrederick Mayle   struct slist* cur_list = list;
255*9712c20fSFrederick Mayle   int step = 1;
256*9712c20fSFrederick Mayle   while (cur_list < list_end && cur_list->n_type == N_PSYM) {
257*9712c20fSFrederick Mayle     ++cur_list;
258*9712c20fSFrederick Mayle     ++step;
259*9712c20fSFrederick Mayle   }
260*9712c20fSFrederick Mayle 
261*9712c20fSFrederick Mayle   func_info->stack_param_size = 0;
262*9712c20fSFrederick Mayle   return step;
263*9712c20fSFrederick Mayle }
264*9712c20fSFrederick Mayle 
LoadLineInfo(struct slist * list,struct slist * list_end,struct FuncInfo * func_info)265*9712c20fSFrederick Mayle int LoadLineInfo(struct slist* list,
266*9712c20fSFrederick Mayle                  struct slist* list_end,
267*9712c20fSFrederick Mayle                  struct FuncInfo* func_info) {
268*9712c20fSFrederick Mayle   struct slist* cur_list = list;
269*9712c20fSFrederick Mayle   do {
270*9712c20fSFrederick Mayle     // Skip non line information.
271*9712c20fSFrederick Mayle     while (cur_list < list_end && cur_list->n_type != N_SLINE) {
272*9712c20fSFrederick Mayle       // Only exit when got another function, or source file, or end stab.
273*9712c20fSFrederick Mayle       if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO ||
274*9712c20fSFrederick Mayle           cur_list->n_type == N_ENDM) {
275*9712c20fSFrederick Mayle         return cur_list - list;
276*9712c20fSFrederick Mayle       }
277*9712c20fSFrederick Mayle       ++cur_list;
278*9712c20fSFrederick Mayle     }
279*9712c20fSFrederick Mayle     struct LineInfo line;
280*9712c20fSFrederick Mayle     while (cur_list < list_end && cur_list->n_type == N_SLINE) {
281*9712c20fSFrederick Mayle       line.rva_to_func = cur_list->n_value;
282*9712c20fSFrederick Mayle       // n_desc is a signed short
283*9712c20fSFrederick Mayle       line.line_num = (unsigned short)cur_list->n_desc;
284*9712c20fSFrederick Mayle       func_info->line_info.push_back(line);
285*9712c20fSFrederick Mayle       ++cur_list;
286*9712c20fSFrederick Mayle     }
287*9712c20fSFrederick Mayle     if (cur_list == list_end && cur_list->n_type == N_ENDM)
288*9712c20fSFrederick Mayle       break;
289*9712c20fSFrederick Mayle   } while (list < list_end);
290*9712c20fSFrederick Mayle 
291*9712c20fSFrederick Mayle   return cur_list - list;
292*9712c20fSFrederick Mayle }
293*9712c20fSFrederick Mayle 
LoadFuncSymbols(struct slist * list,struct slist * list_end,char * stabstr,GElf_Word base,struct SourceFileInfo * source_file_info)294*9712c20fSFrederick Mayle int LoadFuncSymbols(struct slist* list,
295*9712c20fSFrederick Mayle                     struct slist* list_end,
296*9712c20fSFrederick Mayle                     char* stabstr,
297*9712c20fSFrederick Mayle                     GElf_Word base,
298*9712c20fSFrederick Mayle                     struct SourceFileInfo* source_file_info) {
299*9712c20fSFrederick Mayle   struct slist* cur_list = list;
300*9712c20fSFrederick Mayle   assert(cur_list->n_type == N_SO);
301*9712c20fSFrederick Mayle   ++cur_list;
302*9712c20fSFrederick Mayle 
303*9712c20fSFrederick Mayle   source_file_info->func_info.clear();
304*9712c20fSFrederick Mayle   while (cur_list < list_end) {
305*9712c20fSFrederick Mayle     // Go until the function symbol.
306*9712c20fSFrederick Mayle     while (cur_list < list_end && cur_list->n_type != N_FUN) {
307*9712c20fSFrederick Mayle       if (cur_list->n_type == N_SO) {
308*9712c20fSFrederick Mayle         return cur_list - list;
309*9712c20fSFrederick Mayle       }
310*9712c20fSFrederick Mayle       ++cur_list;
311*9712c20fSFrederick Mayle       if (cur_list->n_type == N_ENDM)
312*9712c20fSFrederick Mayle         RecalculateOffset(cur_list, stabstr);
313*9712c20fSFrederick Mayle       continue;
314*9712c20fSFrederick Mayle     }
315*9712c20fSFrederick Mayle     while (cur_list->n_type == N_FUN) {
316*9712c20fSFrederick Mayle       struct FuncInfo func_info;
317*9712c20fSFrederick Mayle       memset(&func_info, 0, sizeof(func_info));
318*9712c20fSFrederick Mayle       func_info.name = stabstr + cur_list->n_strx + stringOffset;
319*9712c20fSFrederick Mayle       // The n_value field is always 0 from stab generated by Sun CC.
320*9712c20fSFrederick Mayle       // TODO(Alfred): Find the correct value.
321*9712c20fSFrederick Mayle       func_info.addr = cur_list->n_value;
322*9712c20fSFrederick Mayle       ++cur_list;
323*9712c20fSFrederick Mayle       if (cur_list->n_type == N_ENDM)
324*9712c20fSFrederick Mayle         RecalculateOffset(cur_list, stabstr);
325*9712c20fSFrederick Mayle       if (cur_list->n_type != N_ESYM && cur_list->n_type != N_ISYM &&
326*9712c20fSFrederick Mayle           cur_list->n_type != N_FUN) {
327*9712c20fSFrederick Mayle         // Stack parameter size.
328*9712c20fSFrederick Mayle         cur_list += LoadStackParamSize(cur_list, list_end, &func_info);
329*9712c20fSFrederick Mayle         // Line info.
330*9712c20fSFrederick Mayle         cur_list += LoadLineInfo(cur_list, list_end, &func_info);
331*9712c20fSFrederick Mayle       }
332*9712c20fSFrederick Mayle       if (cur_list < list_end && cur_list->n_type == N_ENDM)
333*9712c20fSFrederick Mayle         RecalculateOffset(cur_list, stabstr);
334*9712c20fSFrederick Mayle       // Functions in this module should have address bigger than the module
335*9712c20fSFrederick Mayle       // starting address.
336*9712c20fSFrederick Mayle       //
337*9712c20fSFrederick Mayle       // These two values are always 0 with Sun CC.
338*9712c20fSFrederick Mayle       // TODO(Alfred): Get the correct value or remove the condition statement.
339*9712c20fSFrederick Mayle       if (func_info.addr >= source_file_info->addr) {
340*9712c20fSFrederick Mayle         source_file_info->func_info.push_back(func_info);
341*9712c20fSFrederick Mayle       }
342*9712c20fSFrederick Mayle     }
343*9712c20fSFrederick Mayle   }
344*9712c20fSFrederick Mayle   return cur_list - list;
345*9712c20fSFrederick Mayle }
346*9712c20fSFrederick Mayle 
347*9712c20fSFrederick Mayle // Compute size and rva information based on symbols loaded from stab section.
ComputeSizeAndRVA(struct SymbolInfo * symbols)348*9712c20fSFrederick Mayle bool ComputeSizeAndRVA(struct SymbolInfo* symbols) {
349*9712c20fSFrederick Mayle   std::vector<struct SourceFileInfo>* sorted_files =
350*9712c20fSFrederick Mayle     &(symbols->source_file_info);
351*9712c20fSFrederick Mayle   SymbolMap* symbol_entries = &(symbols->symbol_entries);
352*9712c20fSFrederick Mayle   for (size_t i = 0; i < sorted_files->size(); ++i) {
353*9712c20fSFrederick Mayle     struct SourceFileInfo& source_file = (*sorted_files)[i];
354*9712c20fSFrederick Mayle     std::vector<struct FuncInfo>* sorted_functions = &(source_file.func_info);
355*9712c20fSFrederick Mayle     int func_size = sorted_functions->size();
356*9712c20fSFrederick Mayle 
357*9712c20fSFrederick Mayle     for (size_t j = 0; j < func_size; ++j) {
358*9712c20fSFrederick Mayle       struct FuncInfo& func_info = (*sorted_functions)[j];
359*9712c20fSFrederick Mayle       int line_count = func_info.line_info.size();
360*9712c20fSFrederick Mayle 
361*9712c20fSFrederick Mayle       // Discard the ending part of the name.
362*9712c20fSFrederick Mayle       std::string func_name(func_info.name);
363*9712c20fSFrederick Mayle       std::string::size_type last_colon = func_name.find_first_of(':');
364*9712c20fSFrederick Mayle       if (last_colon != std::string::npos)
365*9712c20fSFrederick Mayle         func_name = func_name.substr(0, last_colon);
366*9712c20fSFrederick Mayle 
367*9712c20fSFrederick Mayle       // Fine the symbol offset from the loading address and size by name.
368*9712c20fSFrederick Mayle       SymbolMap::const_iterator it = symbol_entries->find(func_name.c_str());
369*9712c20fSFrederick Mayle       if (it->second) {
370*9712c20fSFrederick Mayle         func_info.rva_to_base = it->second->offset;
371*9712c20fSFrederick Mayle         func_info.size = (line_count == 0) ? 0 : it->second->size;
372*9712c20fSFrederick Mayle       } else {
373*9712c20fSFrederick Mayle         func_info.rva_to_base = 0;
374*9712c20fSFrederick Mayle         func_info.size = 0;
375*9712c20fSFrederick Mayle       }
376*9712c20fSFrederick Mayle 
377*9712c20fSFrederick Mayle       // Compute function and line size.
378*9712c20fSFrederick Mayle       for (size_t k = 0; k < line_count; ++k) {
379*9712c20fSFrederick Mayle         struct LineInfo& line_info = func_info.line_info[k];
380*9712c20fSFrederick Mayle 
381*9712c20fSFrederick Mayle         line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base;
382*9712c20fSFrederick Mayle         if (k == line_count - 1) {
383*9712c20fSFrederick Mayle           line_info.size = func_info.size - line_info.rva_to_func;
384*9712c20fSFrederick Mayle         } else {
385*9712c20fSFrederick Mayle           struct LineInfo& next_line = func_info.line_info[k + 1];
386*9712c20fSFrederick Mayle           line_info.size = next_line.rva_to_func - line_info.rva_to_func;
387*9712c20fSFrederick Mayle         }
388*9712c20fSFrederick Mayle       }  // for each line.
389*9712c20fSFrederick Mayle     }  // for each function.
390*9712c20fSFrederick Mayle   }  // for each source file.
391*9712c20fSFrederick Mayle   for (SymbolMap::iterator it = symbol_entries->begin();
392*9712c20fSFrederick Mayle        it != symbol_entries->end(); ++it) {
393*9712c20fSFrederick Mayle     free(it->second);
394*9712c20fSFrederick Mayle   }
395*9712c20fSFrederick Mayle   return true;
396*9712c20fSFrederick Mayle }
397*9712c20fSFrederick Mayle 
LoadAllSymbols(const GElf_Shdr * stab_section,const GElf_Shdr * stabstr_section,GElf_Word base,struct SymbolInfo * symbols)398*9712c20fSFrederick Mayle bool LoadAllSymbols(const GElf_Shdr* stab_section,
399*9712c20fSFrederick Mayle                     const GElf_Shdr* stabstr_section,
400*9712c20fSFrederick Mayle                     GElf_Word base,
401*9712c20fSFrederick Mayle                     struct SymbolInfo* symbols) {
402*9712c20fSFrederick Mayle   if (stab_section == NULL || stabstr_section == NULL)
403*9712c20fSFrederick Mayle     return false;
404*9712c20fSFrederick Mayle 
405*9712c20fSFrederick Mayle   char* stabstr = reinterpret_cast<char*>(stabstr_section->sh_offset + base);
406*9712c20fSFrederick Mayle   struct slist* lists =
407*9712c20fSFrederick Mayle     reinterpret_cast<struct slist*>(stab_section->sh_offset + base);
408*9712c20fSFrederick Mayle   int nstab = stab_section->sh_size / sizeof(struct slist);
409*9712c20fSFrederick Mayle   int source_id = 0;
410*9712c20fSFrederick Mayle 
411*9712c20fSFrederick Mayle   // First pass, load all symbols from the object file.
412*9712c20fSFrederick Mayle   for (int i = 0; i < nstab; ) {
413*9712c20fSFrederick Mayle     int step = 1;
414*9712c20fSFrederick Mayle     struct slist* cur_list = lists + i;
415*9712c20fSFrederick Mayle     if (cur_list->n_type == N_SO) {
416*9712c20fSFrederick Mayle       // FUNC <address> <size> <param_stack_size> <function>
417*9712c20fSFrederick Mayle       struct SourceFileInfo source_file_info;
418*9712c20fSFrederick Mayle       source_file_info.name = stabstr + cur_list->n_strx + stringOffset;
419*9712c20fSFrederick Mayle       // The n_value field is always 0 from stab generated by Sun CC.
420*9712c20fSFrederick Mayle       // TODO(Alfred): Find the correct value.
421*9712c20fSFrederick Mayle       source_file_info.addr = cur_list->n_value;
422*9712c20fSFrederick Mayle       if (strchr(source_file_info.name, '.'))
423*9712c20fSFrederick Mayle         source_file_info.source_id = source_id++;
424*9712c20fSFrederick Mayle       else
425*9712c20fSFrederick Mayle         source_file_info.source_id = -1;
426*9712c20fSFrederick Mayle       step = LoadFuncSymbols(cur_list, lists + nstab - 1, stabstr,
427*9712c20fSFrederick Mayle                              base, &source_file_info);
428*9712c20fSFrederick Mayle       symbols->source_file_info.push_back(source_file_info);
429*9712c20fSFrederick Mayle     }
430*9712c20fSFrederick Mayle     i += step;
431*9712c20fSFrederick Mayle   }
432*9712c20fSFrederick Mayle   // Second pass, compute the size of functions and lines.
433*9712c20fSFrederick Mayle   return ComputeSizeAndRVA(symbols);
434*9712c20fSFrederick Mayle }
435*9712c20fSFrederick Mayle 
LoadSymbols(Elf * elf,GElf_Ehdr * elf_header,struct SymbolInfo * symbols,void * obj_base)436*9712c20fSFrederick Mayle bool LoadSymbols(Elf* elf, GElf_Ehdr* elf_header, struct SymbolInfo* symbols,
437*9712c20fSFrederick Mayle                  void* obj_base) {
438*9712c20fSFrederick Mayle   GElf_Word base = reinterpret_cast<GElf_Word>(obj_base);
439*9712c20fSFrederick Mayle 
440*9712c20fSFrederick Mayle   const GElf_Shdr* sections =
441*9712c20fSFrederick Mayle     reinterpret_cast<GElf_Shdr*>(elf_header->e_shoff + base);
442*9712c20fSFrederick Mayle   GElf_Shdr stab_section;
443*9712c20fSFrederick Mayle   if (!FindSectionByName(elf, kStabName, elf_header->e_shstrndx,
444*9712c20fSFrederick Mayle                          &stab_section)) {
445*9712c20fSFrederick Mayle     fprintf(stderr, "Stab section not found.\n");
446*9712c20fSFrederick Mayle     return false;
447*9712c20fSFrederick Mayle   }
448*9712c20fSFrederick Mayle   GElf_Shdr stabstr_section;
449*9712c20fSFrederick Mayle   if (!FindSectionByName(elf, kStabStrName, elf_header->e_shstrndx,
450*9712c20fSFrederick Mayle                          &stabstr_section)) {
451*9712c20fSFrederick Mayle     fprintf(stderr, "Stabstr section not found.\n");
452*9712c20fSFrederick Mayle     return false;
453*9712c20fSFrederick Mayle   }
454*9712c20fSFrederick Mayle   GElf_Shdr symtab_section;
455*9712c20fSFrederick Mayle   if (!FindSectionByName(elf, kSymtabName, elf_header->e_shstrndx,
456*9712c20fSFrederick Mayle                          &symtab_section)) {
457*9712c20fSFrederick Mayle     fprintf(stderr, "Symtab section not found.\n");
458*9712c20fSFrederick Mayle     return false;
459*9712c20fSFrederick Mayle   }
460*9712c20fSFrederick Mayle   GElf_Shdr strtab_section;
461*9712c20fSFrederick Mayle   if (!FindSectionByName(elf, kStrtabName, elf_header->e_shstrndx,
462*9712c20fSFrederick Mayle                          &strtab_section)) {
463*9712c20fSFrederick Mayle     fprintf(stderr, "Strtab section not found.\n");
464*9712c20fSFrederick Mayle     return false;
465*9712c20fSFrederick Mayle   }
466*9712c20fSFrederick Mayle 
467*9712c20fSFrederick Mayle   Elf_Sym* symbol = (Elf_Sym*)((char*)base + symtab_section.sh_offset);
468*9712c20fSFrederick Mayle   for (int i = 0; i < symtab_section.sh_size/symtab_section.sh_entsize; ++i) {
469*9712c20fSFrederick Mayle     struct SymbolEntry* symbol_entry =
470*9712c20fSFrederick Mayle         (struct SymbolEntry*)malloc(sizeof(struct SymbolEntry));
471*9712c20fSFrederick Mayle     const char* name = reinterpret_cast<char*>(
472*9712c20fSFrederick Mayle         strtab_section.sh_offset + (GElf_Word)base + symbol->st_name);
473*9712c20fSFrederick Mayle     symbol_entry->offset = symbol->st_value;
474*9712c20fSFrederick Mayle     symbol_entry->size = symbol->st_size;
475*9712c20fSFrederick Mayle     symbols->symbol_entries.insert(make_pair(name, symbol_entry));
476*9712c20fSFrederick Mayle     ++symbol;
477*9712c20fSFrederick Mayle   }
478*9712c20fSFrederick Mayle 
479*9712c20fSFrederick Mayle 
480*9712c20fSFrederick Mayle   // Load symbols.
481*9712c20fSFrederick Mayle   return LoadAllSymbols(&stab_section, &stabstr_section, base, symbols);
482*9712c20fSFrederick Mayle }
483*9712c20fSFrederick Mayle 
WriteModuleInfo(int fd,GElf_Half arch,const std::string & obj_file)484*9712c20fSFrederick Mayle bool WriteModuleInfo(int fd, GElf_Half arch, const std::string& obj_file) {
485*9712c20fSFrederick Mayle   const char* arch_name = NULL;
486*9712c20fSFrederick Mayle   if (arch == EM_386)
487*9712c20fSFrederick Mayle     arch_name = "x86";
488*9712c20fSFrederick Mayle   else if (arch == EM_X86_64)
489*9712c20fSFrederick Mayle     arch_name = "x86_64";
490*9712c20fSFrederick Mayle   else if (arch == EM_SPARC32PLUS)
491*9712c20fSFrederick Mayle     arch_name = "SPARC_32+";
492*9712c20fSFrederick Mayle   else {
493*9712c20fSFrederick Mayle     printf("Please add more ARCH support\n");
494*9712c20fSFrederick Mayle     return false;
495*9712c20fSFrederick Mayle   }
496*9712c20fSFrederick Mayle 
497*9712c20fSFrederick Mayle   unsigned char identifier[16];
498*9712c20fSFrederick Mayle   google_breakpad::elf::FileID file_id(obj_file.c_str());
499*9712c20fSFrederick Mayle   if (file_id.ElfFileIdentifier(identifier)) {
500*9712c20fSFrederick Mayle     char identifier_str[40];
501*9712c20fSFrederick Mayle     file_id.ConvertIdentifierToString(identifier,
502*9712c20fSFrederick Mayle                                       identifier_str, sizeof(identifier_str));
503*9712c20fSFrederick Mayle     std::string filename = obj_file;
504*9712c20fSFrederick Mayle     size_t slash_pos = obj_file.find_last_of("/");
505*9712c20fSFrederick Mayle     if (slash_pos != std::string::npos)
506*9712c20fSFrederick Mayle       filename = obj_file.substr(slash_pos + 1);
507*9712c20fSFrederick Mayle     return WriteFormat(fd, "MODULE solaris %s %s %s\n", arch_name,
508*9712c20fSFrederick Mayle                        identifier_str, filename.c_str());
509*9712c20fSFrederick Mayle   }
510*9712c20fSFrederick Mayle   return false;
511*9712c20fSFrederick Mayle }
512*9712c20fSFrederick Mayle 
WriteSourceFileInfo(int fd,const struct SymbolInfo & symbols)513*9712c20fSFrederick Mayle bool WriteSourceFileInfo(int fd, const struct SymbolInfo& symbols) {
514*9712c20fSFrederick Mayle   for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
515*9712c20fSFrederick Mayle     if (symbols.source_file_info[i].source_id != -1) {
516*9712c20fSFrederick Mayle       const char* name = symbols.source_file_info[i].name;
517*9712c20fSFrederick Mayle       if (!WriteFormat(fd, "FILE %d %s\n",
518*9712c20fSFrederick Mayle                        symbols.source_file_info[i].source_id, name))
519*9712c20fSFrederick Mayle         return false;
520*9712c20fSFrederick Mayle     }
521*9712c20fSFrederick Mayle   }
522*9712c20fSFrederick Mayle   return true;
523*9712c20fSFrederick Mayle }
524*9712c20fSFrederick Mayle 
WriteOneFunction(int fd,int source_id,const struct FuncInfo & func_info)525*9712c20fSFrederick Mayle bool WriteOneFunction(int fd, int source_id,
526*9712c20fSFrederick Mayle                       const struct FuncInfo& func_info){
527*9712c20fSFrederick Mayle   // Discard the ending part of the name.
528*9712c20fSFrederick Mayle   std::string func_name(func_info.name);
529*9712c20fSFrederick Mayle   std::string::size_type last_colon = func_name.find_last_of(':');
530*9712c20fSFrederick Mayle   if (last_colon != std::string::npos)
531*9712c20fSFrederick Mayle     func_name = func_name.substr(0, last_colon);
532*9712c20fSFrederick Mayle   func_name = Demangle(func_name.c_str());
533*9712c20fSFrederick Mayle 
534*9712c20fSFrederick Mayle   if (func_info.size <= 0)
535*9712c20fSFrederick Mayle     return true;
536*9712c20fSFrederick Mayle 
537*9712c20fSFrederick Mayle   // rva_to_base could be unsigned long(32 bit) or unsigned long long(64 bit).
538*9712c20fSFrederick Mayle   if (WriteFormat(fd, "FUNC %llx %x %d %s\n",
539*9712c20fSFrederick Mayle                   (long long)func_info.rva_to_base,
540*9712c20fSFrederick Mayle                   func_info.size,
541*9712c20fSFrederick Mayle                   func_info.stack_param_size,
542*9712c20fSFrederick Mayle                   func_name.c_str())) {
543*9712c20fSFrederick Mayle     for (size_t i = 0; i < func_info.line_info.size(); ++i) {
544*9712c20fSFrederick Mayle       const struct LineInfo& line_info = func_info.line_info[i];
545*9712c20fSFrederick Mayle       if (line_info.line_num == 0)
546*9712c20fSFrederick Mayle         return true;
547*9712c20fSFrederick Mayle       if (!WriteFormat(fd, "%llx %x %d %d\n",
548*9712c20fSFrederick Mayle                        (long long)line_info.rva_to_base,
549*9712c20fSFrederick Mayle                        line_info.size,
550*9712c20fSFrederick Mayle                        line_info.line_num,
551*9712c20fSFrederick Mayle                        source_id))
552*9712c20fSFrederick Mayle         return false;
553*9712c20fSFrederick Mayle     }
554*9712c20fSFrederick Mayle     return true;
555*9712c20fSFrederick Mayle   }
556*9712c20fSFrederick Mayle   return false;
557*9712c20fSFrederick Mayle }
558*9712c20fSFrederick Mayle 
WriteFunctionInfo(int fd,const struct SymbolInfo & symbols)559*9712c20fSFrederick Mayle bool WriteFunctionInfo(int fd, const struct SymbolInfo& symbols) {
560*9712c20fSFrederick Mayle   for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
561*9712c20fSFrederick Mayle     const struct SourceFileInfo& file_info = symbols.source_file_info[i];
562*9712c20fSFrederick Mayle     for (size_t j = 0; j < file_info.func_info.size(); ++j) {
563*9712c20fSFrederick Mayle       const struct FuncInfo& func_info = file_info.func_info[j];
564*9712c20fSFrederick Mayle       if (!WriteOneFunction(fd, file_info.source_id, func_info))
565*9712c20fSFrederick Mayle         return false;
566*9712c20fSFrederick Mayle     }
567*9712c20fSFrederick Mayle   }
568*9712c20fSFrederick Mayle   return true;
569*9712c20fSFrederick Mayle }
570*9712c20fSFrederick Mayle 
DumpStabSymbols(int fd,const struct SymbolInfo & symbols)571*9712c20fSFrederick Mayle bool DumpStabSymbols(int fd, const struct SymbolInfo& symbols) {
572*9712c20fSFrederick Mayle   return WriteSourceFileInfo(fd, symbols) &&
573*9712c20fSFrederick Mayle     WriteFunctionInfo(fd, symbols);
574*9712c20fSFrederick Mayle }
575*9712c20fSFrederick Mayle 
576*9712c20fSFrederick Mayle //
577*9712c20fSFrederick Mayle // FDWrapper
578*9712c20fSFrederick Mayle //
579*9712c20fSFrederick Mayle // Wrapper class to make sure opened file is closed.
580*9712c20fSFrederick Mayle //
581*9712c20fSFrederick Mayle class FDWrapper {
582*9712c20fSFrederick Mayle  public:
FDWrapper(int fd)583*9712c20fSFrederick Mayle   explicit FDWrapper(int fd) :
584*9712c20fSFrederick Mayle     fd_(fd) {
585*9712c20fSFrederick Mayle     }
~FDWrapper()586*9712c20fSFrederick Mayle   ~FDWrapper() {
587*9712c20fSFrederick Mayle     if (fd_ != -1)
588*9712c20fSFrederick Mayle       close(fd_);
589*9712c20fSFrederick Mayle   }
get()590*9712c20fSFrederick Mayle   int get() {
591*9712c20fSFrederick Mayle     return fd_;
592*9712c20fSFrederick Mayle   }
release()593*9712c20fSFrederick Mayle   int release() {
594*9712c20fSFrederick Mayle     int fd = fd_;
595*9712c20fSFrederick Mayle     fd_ = -1;
596*9712c20fSFrederick Mayle     return fd;
597*9712c20fSFrederick Mayle   }
598*9712c20fSFrederick Mayle  private:
599*9712c20fSFrederick Mayle   int fd_;
600*9712c20fSFrederick Mayle };
601*9712c20fSFrederick Mayle 
602*9712c20fSFrederick Mayle //
603*9712c20fSFrederick Mayle // MmapWrapper
604*9712c20fSFrederick Mayle //
605*9712c20fSFrederick Mayle // Wrapper class to make sure mapped regions are unmapped.
606*9712c20fSFrederick Mayle //
607*9712c20fSFrederick Mayle class MmapWrapper {
608*9712c20fSFrederick Mayle  public:
MmapWrapper(void * mapped_address,size_t mapped_size)609*9712c20fSFrederick Mayle   MmapWrapper(void* mapped_address, size_t mapped_size) :
610*9712c20fSFrederick Mayle     base_(mapped_address), size_(mapped_size) {
611*9712c20fSFrederick Mayle   }
~MmapWrapper()612*9712c20fSFrederick Mayle   ~MmapWrapper() {
613*9712c20fSFrederick Mayle     if (base_ != NULL) {
614*9712c20fSFrederick Mayle       assert(size_ > 0);
615*9712c20fSFrederick Mayle       munmap((char*)base_, size_);
616*9712c20fSFrederick Mayle     }
617*9712c20fSFrederick Mayle   }
release()618*9712c20fSFrederick Mayle   void release() {
619*9712c20fSFrederick Mayle     base_ = NULL;
620*9712c20fSFrederick Mayle     size_ = 0;
621*9712c20fSFrederick Mayle   }
622*9712c20fSFrederick Mayle 
623*9712c20fSFrederick Mayle  private:
624*9712c20fSFrederick Mayle   void* base_;
625*9712c20fSFrederick Mayle   size_t size_;
626*9712c20fSFrederick Mayle };
627*9712c20fSFrederick Mayle 
628*9712c20fSFrederick Mayle }  // namespace
629*9712c20fSFrederick Mayle 
630*9712c20fSFrederick Mayle namespace google_breakpad {
631*9712c20fSFrederick Mayle 
632*9712c20fSFrederick Mayle class AutoElfEnder {
633*9712c20fSFrederick Mayle  public:
AutoElfEnder(Elf * elf)634*9712c20fSFrederick Mayle   AutoElfEnder(Elf* elf) : elf_(elf) {}
~AutoElfEnder()635*9712c20fSFrederick Mayle   ~AutoElfEnder() { if (elf_) elf_end(elf_); }
636*9712c20fSFrederick Mayle  private:
637*9712c20fSFrederick Mayle   Elf* elf_;
638*9712c20fSFrederick Mayle };
639*9712c20fSFrederick Mayle 
640*9712c20fSFrederick Mayle 
WriteSymbolFile(const std::string & obj_file,int sym_fd)641*9712c20fSFrederick Mayle bool DumpSymbols::WriteSymbolFile(const std::string& obj_file, int sym_fd) {
642*9712c20fSFrederick Mayle   if (elf_version(EV_CURRENT) == EV_NONE) {
643*9712c20fSFrederick Mayle     fprintf(stderr, "elf_version() failed: %s\n", elf_errmsg(0));
644*9712c20fSFrederick Mayle     return false;
645*9712c20fSFrederick Mayle   }
646*9712c20fSFrederick Mayle 
647*9712c20fSFrederick Mayle   int obj_fd = open(obj_file.c_str(), O_RDONLY);
648*9712c20fSFrederick Mayle   if (obj_fd < 0)
649*9712c20fSFrederick Mayle     return false;
650*9712c20fSFrederick Mayle   FDWrapper obj_fd_wrapper(obj_fd);
651*9712c20fSFrederick Mayle   struct stat st;
652*9712c20fSFrederick Mayle   if (fstat(obj_fd, &st) != 0 && st.st_size <= 0)
653*9712c20fSFrederick Mayle     return false;
654*9712c20fSFrederick Mayle   void* obj_base = mmap(NULL, st.st_size,
655*9712c20fSFrederick Mayle                         PROT_READ, MAP_PRIVATE, obj_fd, 0);
656*9712c20fSFrederick Mayle   if (obj_base == MAP_FAILED)
657*9712c20fSFrederick Mayle     return false;
658*9712c20fSFrederick Mayle   MmapWrapper map_wrapper(obj_base, st.st_size);
659*9712c20fSFrederick Mayle   GElf_Ehdr elf_header;
660*9712c20fSFrederick Mayle   Elf* elf = elf_begin(obj_fd, ELF_C_READ, NULL);
661*9712c20fSFrederick Mayle   AutoElfEnder elfEnder(elf);
662*9712c20fSFrederick Mayle 
663*9712c20fSFrederick Mayle   if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr*)NULL) {
664*9712c20fSFrederick Mayle     fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1));
665*9712c20fSFrederick Mayle     return false;
666*9712c20fSFrederick Mayle   }
667*9712c20fSFrederick Mayle 
668*9712c20fSFrederick Mayle   if (!IsValidElf(&elf_header)) {
669*9712c20fSFrederick Mayle     fprintf(stderr, "header magic doesn't match\n");
670*9712c20fSFrederick Mayle     return false;
671*9712c20fSFrederick Mayle   }
672*9712c20fSFrederick Mayle   struct SymbolInfo symbols;
673*9712c20fSFrederick Mayle   if (!LoadSymbols(elf, &elf_header, &symbols, obj_base))
674*9712c20fSFrederick Mayle     return false;
675*9712c20fSFrederick Mayle   // Write to symbol file.
676*9712c20fSFrederick Mayle   if (WriteModuleInfo(sym_fd, elf_header.e_machine, obj_file) &&
677*9712c20fSFrederick Mayle       DumpStabSymbols(sym_fd, symbols))
678*9712c20fSFrederick Mayle     return true;
679*9712c20fSFrederick Mayle 
680*9712c20fSFrederick Mayle   return false;
681*9712c20fSFrederick Mayle }
682*9712c20fSFrederick Mayle 
683*9712c20fSFrederick Mayle }  // namespace google_breakpad
684