blob: 21860e1e4fbc070ea3686cfd90d5cec1be19ace8 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ObjectFileMachO.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ObjectFileMachO.h"
11
12#include <mach-o/nlist.h>
13#include <mach-o/stab.h>
14
15#include "lldb/Core/ArchSpec.h"
16#include "lldb/Core/DataBuffer.h"
17#include "lldb/Core/FileSpec.h"
18#include "lldb/Core/FileSpecList.h"
19#include "lldb/Core/Module.h"
20#include "lldb/Core/PluginManager.h"
21#include "lldb/Core/Section.h"
22#include "lldb/Core/StreamFile.h"
23#include "lldb/Core/StreamString.h"
24#include "lldb/Core/Timer.h"
25#include "lldb/Core/UUID.h"
26#include "lldb/Symbol/ObjectFile.h"
27
28#ifndef S_DTRACE_DOF
29// section contains DTrace Object Format
30#define S_DTRACE_DOF 0xf
31#endif
32
33#ifndef S_LAZY_DYLIB_SYMBOL_POINTERS
34// section with only lazy symbol pointers to lazy loaded dylibs
35#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10
36#endif
37
38using namespace lldb;
39using namespace lldb_private;
40
41
42void
43ObjectFileMachO::Initialize()
44{
45 PluginManager::RegisterPlugin (GetPluginNameStatic(),
46 GetPluginDescriptionStatic(),
47 CreateInstance);
48}
49
50void
51ObjectFileMachO::Terminate()
52{
53 PluginManager::UnregisterPlugin (CreateInstance);
54}
55
56
57const char *
58ObjectFileMachO::GetPluginNameStatic()
59{
60 return "object-file.mach-o";
61}
62
63const char *
64ObjectFileMachO::GetPluginDescriptionStatic()
65{
66 return "Mach-o object file reader (32 and 64 bit)";
67}
68
69
70ObjectFile *
71ObjectFileMachO::CreateInstance (Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
72{
73 if (ObjectFileMachO::MagicBytesMatch(dataSP))
74 {
75 std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module, dataSP, file, offset, length));
76 if (objfile_ap.get() && objfile_ap->ParseHeader())
77 return objfile_ap.release();
78 }
79 return NULL;
80}
81
82
83static uint32_t
84MachHeaderSizeFromMagic(uint32_t magic)
85{
86 switch (magic)
87 {
88 case MH_MAGIC:
89 case MH_CIGAM:
90 return sizeof(struct mach_header);
91
92 case MH_MAGIC_64:
93 case MH_CIGAM_64:
94 return sizeof(struct mach_header_64);
95 break;
96
97 default:
98 break;
99 }
100 return 0;
101}
102
103
104bool
105ObjectFileMachO::MagicBytesMatch (DataBufferSP& dataSP)
106{
107 DataExtractor data(dataSP, eByteOrderHost, 4);
108 uint32_t offset = 0;
109 uint32_t magic = data.GetU32(&offset);
110 return MachHeaderSizeFromMagic(magic) != 0;
111}
112
113
114ObjectFileMachO::ObjectFileMachO(Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length) :
115 ObjectFile(module, file, offset, length, dataSP),
116 m_mutex (Mutex::eMutexTypeRecursive),
117 m_header(),
118 m_sections_ap(),
119 m_symtab_ap()
120{
121 ::bzero (&m_header, sizeof(m_header));
122 ::bzero (&m_dysymtab, sizeof(m_dysymtab));
123}
124
125
126ObjectFileMachO::~ObjectFileMachO()
127{
128}
129
130
131bool
132ObjectFileMachO::ParseHeader ()
133{
134 lldb_private::Mutex::Locker locker(m_mutex);
135 bool can_parse = false;
136 uint32_t offset = 0;
137 m_data.SetByteOrder (eByteOrderHost);
138 // Leave magic in the original byte order
139 m_header.magic = m_data.GetU32(&offset);
140 switch (m_header.magic)
141 {
142 case MH_MAGIC:
143 m_data.SetByteOrder (eByteOrderHost);
144 m_data.SetAddressByteSize(4);
145 can_parse = true;
146 break;
147
148 case MH_MAGIC_64:
149 m_data.SetByteOrder (eByteOrderHost);
150 m_data.SetAddressByteSize(8);
151 can_parse = true;
152 break;
153
154 case MH_CIGAM:
155 m_data.SetByteOrder(eByteOrderHost == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
156 m_data.SetAddressByteSize(4);
157 can_parse = true;
158 break;
159
160 case MH_CIGAM_64:
161 m_data.SetByteOrder(eByteOrderHost == eByteOrderBig ? eByteOrderLittle : eByteOrderBig);
162 m_data.SetAddressByteSize(8);
163 can_parse = true;
164 break;
165
166 default:
167 break;
168 }
169
170 if (can_parse)
171 {
172 m_data.GetU32(&offset, &m_header.cputype, 6);
173
Greg Clayton41f92322010-06-11 03:25:34 +0000174 ArchSpec mach_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175 if (mach_arch == m_module->GetArchitecture())
176 {
177 // Read in all only the load command data
178 DataBufferSP data_sp(m_file.ReadFileContents(m_offset, m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic)));
179 m_data.SetData (data_sp);
180 return true;
181 }
182 }
183 else
184 {
185 memset(&m_header, 0, sizeof(struct mach_header));
186 }
187 return false;
188}
189
190
191ByteOrder
192ObjectFileMachO::GetByteOrder () const
193{
194 lldb_private::Mutex::Locker locker(m_mutex);
195 return m_data.GetByteOrder ();
196}
197
198
199size_t
200ObjectFileMachO::GetAddressByteSize () const
201{
202 lldb_private::Mutex::Locker locker(m_mutex);
203 return m_data.GetAddressByteSize ();
204}
205
206
207Symtab *
208ObjectFileMachO::GetSymtab()
209{
210 lldb_private::Mutex::Locker locker(m_mutex);
211 if (m_symtab_ap.get() == NULL)
212 {
213 m_symtab_ap.reset(new Symtab(this));
214 ParseSymtab(false);
215 }
216 return m_symtab_ap.get();
217}
218
219
220SectionList *
221ObjectFileMachO::GetSectionList()
222{
223 lldb_private::Mutex::Locker locker(m_mutex);
224 if (m_sections_ap.get() == NULL)
225 {
226 m_sections_ap.reset(new SectionList());
227 ParseSections();
228 }
229 return m_sections_ap.get();
230}
231
232
233size_t
234ObjectFileMachO::ParseSections ()
235{
236 lldb::user_id_t segID = 0;
237 lldb::user_id_t sectID = 0;
238 struct segment_command_64 load_cmd;
239 uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
240 uint32_t i;
241 //bool dump_sections = false;
242 for (i=0; i<m_header.ncmds; ++i)
243 {
244 const uint32_t load_cmd_offset = offset;
245 if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
246 break;
247
248 if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64)
249 {
250 if (m_data.GetU8(&offset, (uint8_t*)load_cmd.segname, 16))
251 {
252 load_cmd.vmaddr = m_data.GetAddress(&offset);
253 load_cmd.vmsize = m_data.GetAddress(&offset);
254 load_cmd.fileoff = m_data.GetAddress(&offset);
255 load_cmd.filesize = m_data.GetAddress(&offset);
256 if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
257 {
258 // Keep a list of mach segments around in case we need to
259 // get at data that isn't stored in the abstracted Sections.
260 m_mach_segments.push_back (load_cmd);
261
262 ConstString segment_name (load_cmd.segname, std::min<int>(strlen(load_cmd.segname), sizeof(load_cmd.segname)));
263 // Use a segment ID of the segment index shifted left by 8 so they
264 // never conflict with any of the sections.
265 SectionSP segment_sp;
266 if (segment_name)
267 {
268 segment_sp.reset(new Section (NULL,
269 GetModule(), // Module to which this section belongs
270 ++segID << 8, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
271 segment_name, // Name of this section
272 eSectionTypeContainer, // This section is a container of other sections.
273 load_cmd.vmaddr, // File VM address == addresses as they are found in the object file
274 load_cmd.vmsize, // VM size in bytes of this section
275 load_cmd.fileoff, // Offset to the data for this section in the file
276 load_cmd.filesize, // Size in bytes of this section as found in the the file
277 load_cmd.flags)); // Flags for this section
278
279 m_sections_ap->AddSection(segment_sp);
280 }
281
282 struct section_64 sect64;
283 ::bzero (&sect64, sizeof(sect64));
284 // Push a section into our mach sections for the section at
285 // index zero (NO_SECT)
286 m_mach_sections.push_back(sect64);
287 uint32_t segment_sect_idx;
288 const lldb::user_id_t first_segment_sectID = sectID + 1;
289
290
291 const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8;
292 for (segment_sect_idx=0; segment_sect_idx<load_cmd.nsects; ++segment_sect_idx)
293 {
294 if (m_data.GetU8(&offset, (uint8_t*)sect64.sectname, sizeof(sect64.sectname)) == NULL)
295 break;
296 if (m_data.GetU8(&offset, (uint8_t*)sect64.segname, sizeof(sect64.segname)) == NULL)
297 break;
298 sect64.addr = m_data.GetAddress(&offset);
299 sect64.size = m_data.GetAddress(&offset);
300
301 if (m_data.GetU32(&offset, &sect64.offset, num_u32s) == NULL)
302 break;
303
304 // Keep a list of mach sections around in case we need to
305 // get at data that isn't stored in the abstracted Sections.
306 m_mach_sections.push_back (sect64);
307
308 ConstString section_name (sect64.sectname, std::min<size_t>(strlen(sect64.sectname), sizeof(sect64.sectname)));
309 if (!segment_name)
310 {
311 // We have a segment with no name so we need to conjure up
312 // segments that correspond to the section's segname if there
313 // isn't already such a section. If there is such a section,
314 // we resize the section so that it spans all sections.
315 // We also mark these sections as fake so address matches don't
316 // hit if they land in the gaps between the child sections.
317 segment_name.SetTrimmedCStringWithLength(sect64.segname, sizeof(sect64.segname));
318 segment_sp = m_sections_ap->FindSectionByName (segment_name);
319 if (segment_sp.get())
320 {
321 Section *segment = segment_sp.get();
322 // Grow the section size as needed.
323 const lldb::addr_t sect64_min_addr = sect64.addr;
324 const lldb::addr_t sect64_max_addr = sect64_min_addr + sect64.size;
325 const lldb::addr_t curr_seg_byte_size = segment->GetByteSize();
326 const lldb::addr_t curr_seg_min_addr = segment->GetFileAddress();
327 const lldb::addr_t curr_seg_max_addr = curr_seg_min_addr + curr_seg_byte_size;
328 if (sect64_min_addr >= curr_seg_min_addr)
329 {
330 const lldb::addr_t new_seg_byte_size = sect64_max_addr - curr_seg_min_addr;
331 // Only grow the section size if needed
332 if (new_seg_byte_size > curr_seg_byte_size)
333 segment->SetByteSize (new_seg_byte_size);
334 }
335 else
336 {
337 // We need to change the base address of the segment and
338 // adjust the child section offsets for all existing children.
339 const lldb::addr_t slide_amount = sect64_min_addr - curr_seg_min_addr;
340 segment->Slide(slide_amount, false);
341 segment->GetChildren().Slide (-slide_amount, false);
342 segment->SetByteSize (curr_seg_max_addr - sect64_min_addr);
343 }
344 }
345 else
346 {
347 // Create a fake section for the section's named segment
348 segment_sp.reset(new Section(segment_sp.get(), // Parent section
349 GetModule(), // Module to which this section belongs
350 ++segID << 8, // Section ID is the 1 based segment index shifted right by 8 bits as not to collide with any of the 256 section IDs that are possible
351 segment_name, // Name of this section
352 eSectionTypeContainer, // This section is a container of other sections.
353 sect64.addr, // File VM address == addresses as they are found in the object file
354 sect64.size, // VM size in bytes of this section
355 sect64.offset, // Offset to the data for this section in the file
356 sect64.offset ? sect64.size : 0, // Size in bytes of this section as found in the the file
357 load_cmd.flags)); // Flags for this section
358 segment_sp->SetIsFake(true);
359 m_sections_ap->AddSection(segment_sp);
360 }
361 }
362 assert (segment_sp.get());
363
364 uint32_t mach_sect_type = sect64.flags & SECTION_TYPE;
365 static ConstString g_sect_name_objc_data ("__objc_data");
366 static ConstString g_sect_name_objc_msgrefs ("__objc_msgrefs");
367 static ConstString g_sect_name_objc_selrefs ("__objc_selrefs");
368 static ConstString g_sect_name_objc_classrefs ("__objc_classrefs");
369 static ConstString g_sect_name_objc_superrefs ("__objc_superrefs");
370 static ConstString g_sect_name_objc_const ("__objc_const");
371 static ConstString g_sect_name_objc_classlist ("__objc_classlist");
372 static ConstString g_sect_name_cfstring ("__cfstring");
373 SectionType sect_type = eSectionTypeOther;
374
375 if (section_name == g_sect_name_objc_selrefs)
376 {
377 sect_type = eSectionTypeDataCStringPointers;
378 }
379 else if (section_name == g_sect_name_objc_msgrefs)
380 {
381 sect_type = eSectionTypeDataObjCMessageRefs;
382 }
383 else if (section_name == g_sect_name_objc_data ||
384 section_name == g_sect_name_objc_classrefs ||
385 section_name == g_sect_name_objc_superrefs ||
386 section_name == g_sect_name_objc_const ||
387 section_name == g_sect_name_objc_classlist)
388 {
389 sect_type = eSectionTypeDataPointers;
390 }
391 else if (section_name == g_sect_name_cfstring)
392 {
393 sect_type = eSectionTypeDataObjCCFStrings;
394 }
395
396 if (sect_type == eSectionTypeOther)
397 {
398 switch (mach_sect_type)
399 {
400 // TODO: categorize sections by other flags for regular sections
401 case S_REGULAR:
402
403 sect_type = eSectionTypeOther;
404 break;
405 case S_ZEROFILL: sect_type = eSectionTypeZeroFill; break;
406 case S_CSTRING_LITERALS: sect_type = eSectionTypeDataCString; break; // section with only literal C strings
407 case S_4BYTE_LITERALS: sect_type = eSectionTypeData4; break; // section with only 4 byte literals
408 case S_8BYTE_LITERALS: sect_type = eSectionTypeData8; break; // section with only 8 byte literals
409 case S_LITERAL_POINTERS: sect_type = eSectionTypeDataPointers; break; // section with only pointers to literals
410 case S_NON_LAZY_SYMBOL_POINTERS: sect_type = eSectionTypeDataPointers; break; // section with only non-lazy symbol pointers
411 case S_LAZY_SYMBOL_POINTERS: sect_type = eSectionTypeDataPointers; break; // section with only lazy symbol pointers
412 case S_SYMBOL_STUBS: sect_type = eSectionTypeCode; break; // section with only symbol stubs, byte size of stub in the reserved2 field
413 case S_MOD_INIT_FUNC_POINTERS: sect_type = eSectionTypeDataPointers; break; // section with only function pointers for initialization
414 case S_MOD_TERM_FUNC_POINTERS: sect_type = eSectionTypeDataPointers; break; // section with only function pointers for termination
415 case S_COALESCED: sect_type = eSectionTypeOther; break;
416 case S_GB_ZEROFILL: sect_type = eSectionTypeZeroFill; break;
417 case S_INTERPOSING: sect_type = eSectionTypeCode; break; // section with only pairs of function pointers for interposing
418 case S_16BYTE_LITERALS: sect_type = eSectionTypeData16; break; // section with only 16 byte literals
419 case S_DTRACE_DOF: sect_type = eSectionTypeDebug; break;
420 case S_LAZY_DYLIB_SYMBOL_POINTERS: sect_type = eSectionTypeDataPointers; break;
421 default: break;
422 }
423 }
424
425 SectionSP section_sp(new Section(segment_sp.get(),
426 GetModule(),
427 ++sectID,
428 section_name,
429 sect_type,
430 sect64.addr - segment_sp->GetFileAddress(),
431 sect64.size,
432 sect64.offset,
433 sect64.offset == 0 ? 0 : sect64.size,
434 sect64.flags));
435 segment_sp->GetChildren().AddSection(section_sp);
436
437 if (segment_sp->IsFake())
438 {
439 segment_sp.reset();
440 segment_name.Clear();
441 }
442 }
443 if (m_header.filetype == MH_DSYM)
444 {
445 if (first_segment_sectID <= sectID)
446 {
447 lldb::user_id_t sect_uid;
448 for (sect_uid = first_segment_sectID; sect_uid <= sectID; ++sect_uid)
449 {
450 SectionSP curr_section_sp(segment_sp->GetChildren().FindSectionByID (sect_uid));
451 SectionSP next_section_sp;
452 if (sect_uid + 1 <= sectID)
453 next_section_sp = segment_sp->GetChildren().FindSectionByID (sect_uid+1);
454
455 if (curr_section_sp.get())
456 {
457 if (curr_section_sp->GetByteSize() == 0)
458 {
459 if (next_section_sp.get() != NULL)
460 curr_section_sp->SetByteSize ( next_section_sp->GetFileAddress() - curr_section_sp->GetFileAddress() );
461 else
462 curr_section_sp->SetByteSize ( load_cmd.vmsize );
463 }
464 }
465 }
466 }
467 }
468 }
469 }
470 }
471 else if (load_cmd.cmd == LC_DYSYMTAB)
472 {
473 m_dysymtab.cmd = load_cmd.cmd;
474 m_dysymtab.cmdsize = load_cmd.cmdsize;
475 m_data.GetU32 (&offset, &m_dysymtab.ilocalsym, (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2);
476 }
477
478 offset = load_cmd_offset + load_cmd.cmdsize;
479 }
480// if (dump_sections)
481// {
482// StreamFile s(stdout);
483// m_sections_ap->Dump(&s, true);
484// }
485 return sectID; // Return the number of sections we registered with the module
486}
487
488class MachSymtabSectionInfo
489{
490public:
491
492 MachSymtabSectionInfo (SectionList *section_list) :
493 m_section_list (section_list),
494 m_section_infos()
495 {
496 // Get the number of sections down to a depth of 1 to include
497 // all segments and their sections, but no other sections that
498 // may be added for debug map or
499 m_section_infos.resize(section_list->GetNumSections(1));
500 }
501
502
503 Section *
504 GetSection (uint8_t n_sect, addr_t file_addr)
505 {
506 if (n_sect == 0)
507 return NULL;
508 if (n_sect < m_section_infos.size())
509 {
510 if (m_section_infos[n_sect].section == NULL)
511 {
512 Section *section = m_section_list->FindSectionByID (n_sect).get();
513 m_section_infos[n_sect].section = section;
514 assert (section != NULL);
515 m_section_infos[n_sect].vm_range.SetBaseAddress (section->GetFileAddress());
516 m_section_infos[n_sect].vm_range.SetByteSize (section->GetByteSize());
517 }
518 if (m_section_infos[n_sect].vm_range.Contains(file_addr))
519 return m_section_infos[n_sect].section;
520 }
521 return m_section_list->FindSectionContainingFileAddress(file_addr).get();
522 }
523
524protected:
525 struct SectionInfo
526 {
527 SectionInfo () :
528 vm_range(),
529 section (NULL)
530 {
531 }
532
533 VMRange vm_range;
534 Section *section;
535 };
536 SectionList *m_section_list;
537 std::vector<SectionInfo> m_section_infos;
538};
539
540
541
542size_t
543ObjectFileMachO::ParseSymtab (bool minimize)
544{
545 Timer scoped_timer(__PRETTY_FUNCTION__,
546 "ObjectFileMachO::ParseSymtab () module = %s",
547 m_file.GetFilename().AsCString(""));
548 struct symtab_command symtab_load_command;
549 uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
550 uint32_t i;
551 for (i=0; i<m_header.ncmds; ++i)
552 {
553 const uint32_t cmd_offset = offset;
554 // Read in the load command and load command size
555 if (m_data.GetU32(&offset, &symtab_load_command, 2) == NULL)
556 break;
557 // Watch for the symbol table load command
558 if (symtab_load_command.cmd == LC_SYMTAB)
559 {
560 // Read in the rest of the symtab load command
561 if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4))
562 {
563 Symtab *symtab = m_symtab_ap.get();
564 SectionList *section_list = GetSectionList();
565 assert(section_list);
566 const size_t addr_size = m_data.GetAddressByteSize();
567 const ByteOrder endian = m_data.GetByteOrder();
568 bool bit_width_32 = addr_size == 4;
569 const size_t nlist_size = bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64);
570
571 DataBufferSP symtab_data_sp(m_file.ReadFileContents(m_offset + symtab_load_command.symoff, symtab_load_command.nsyms * nlist_size));
572 DataBufferSP strtab_data_sp(m_file.ReadFileContents(m_offset + symtab_load_command.stroff, symtab_load_command.strsize));
573
574 const char *strtab_data = (const char *)strtab_data_sp->GetBytes();
575// DataExtractor symtab_data(symtab_data_sp, endian, addr_size);
576// DataExtractor strtab_data(strtab_data_sp, endian, addr_size);
577
578 static ConstString g_segment_name_TEXT ("__TEXT");
579 static ConstString g_segment_name_DATA ("__DATA");
580 static ConstString g_segment_name_OBJC ("__OBJC");
581 static ConstString g_section_name_eh_frame ("__eh_frame");
582 SectionSP text_section_sp(section_list->FindSectionByName(g_segment_name_TEXT));
583 SectionSP data_section_sp(section_list->FindSectionByName(g_segment_name_DATA));
584 SectionSP objc_section_sp(section_list->FindSectionByName(g_segment_name_OBJC));
585 SectionSP eh_frame_section_sp;
586 if (text_section_sp.get())
587 eh_frame_section_sp = text_section_sp->GetChildren().FindSectionByName (g_section_name_eh_frame);
588 else
589 eh_frame_section_sp = section_list->FindSectionByName (g_section_name_eh_frame);
590
591 uint8_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : NO_SECT;
592 //uint32_t symtab_offset = 0;
593 const uint8_t* nlist_data = symtab_data_sp->GetBytes();
594 assert (symtab_data_sp->GetByteSize()/nlist_size >= symtab_load_command.nsyms);
595
596
597 if (endian != eByteOrderHost)
598 {
599 // ...
600 assert (!"UNIMPLEMENTED: Swap all nlist entries");
601 }
602 uint32_t N_SO_index = UINT_MAX;
603
604 MachSymtabSectionInfo section_info (section_list);
605 std::vector<uint32_t> N_FUN_indexes;
606 std::vector<uint32_t> N_NSYM_indexes;
607 std::vector<uint32_t> N_INCL_indexes;
608 std::vector<uint32_t> N_BRAC_indexes;
609 std::vector<uint32_t> N_COMM_indexes;
610 uint32_t nlist_idx = 0;
611 Symbol *symbol_ptr = NULL;
612
613 uint32_t sym_idx = 0;
614 Symbol *sym = symtab->Resize (symtab_load_command.nsyms + m_dysymtab.nindirectsyms);
615 uint32_t num_syms = symtab->GetNumSymbols();
616
617 //symtab->Reserve (symtab_load_command.nsyms + m_dysymtab.nindirectsyms);
618 for (nlist_idx = 0; nlist_idx < symtab_load_command.nsyms; ++nlist_idx)
619 {
620 struct nlist_64 nlist;
621 if (bit_width_32)
622 {
623 struct nlist* nlist32_ptr = (struct nlist*)(nlist_data + (nlist_idx * nlist_size));
624 nlist.n_un.n_strx = nlist32_ptr->n_un.n_strx;
625 nlist.n_type = nlist32_ptr->n_type;
626 nlist.n_sect = nlist32_ptr->n_sect;
627 nlist.n_desc = nlist32_ptr->n_desc;
628 nlist.n_value = nlist32_ptr->n_value;
629 }
630 else
631 {
632 nlist = *((struct nlist_64*)(nlist_data + (nlist_idx * nlist_size)));
633 }
634
635 SymbolType type = eSymbolTypeInvalid;
636 const char* symbol_name = &strtab_data[nlist.n_un.n_strx];
637 if (symbol_name[0] == '\0')
638 symbol_name = NULL;
639 Section* symbol_section = NULL;
640 bool add_nlist = true;
641 bool is_debug = ((nlist.n_type & N_STAB) != 0);
642
643 assert (sym_idx < num_syms);
644
645 sym[sym_idx].SetDebug (is_debug);
646
647 if (is_debug)
648 {
649 switch (nlist.n_type)
650 {
651 case N_GSYM: // global symbol: name,,NO_SECT,type,0
652 // Sometimes the N_GSYM value contains the address.
653 if (nlist.n_value != 0)
654 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
655 type = eSymbolTypeGlobal;
656 break;
657
658 case N_FNAME: // procedure name (f77 kludge): name,,NO_SECT,0,0
659 type = eSymbolTypeFunction;
660 break;
661
662 case N_FUN: // procedure: name,,n_sect,linenumber,address
663 if (symbol_name)
664 {
665 type = eSymbolTypeFunction;
666 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
667 // We use the current number of symbols in the symbol table in lieu of
668 // using nlist_idx in case we ever start trimming entries out
669 N_FUN_indexes.push_back(sym_idx);
670 }
671 else
672 {
673 type = eSymbolTypeFunctionEnd;
674
675 if ( !N_FUN_indexes.empty() )
676 {
677 // Copy the size of the function into the original STAB entry so we don't have
678 // to hunt for it later
679 symtab->SymbolAtIndex(N_FUN_indexes.back())->SetByteSize(nlist.n_value);
680 N_FUN_indexes.pop_back();
681 // We dont' really need the end function STAB as it contains the size which
682 // we already placed with the original symbol, so don't add it if we want a
683 // minimal symbol table
684 if (minimize)
685 add_nlist = false;
686 }
687 }
688 break;
689
690 case N_STSYM: // static symbol: name,,n_sect,type,address
691 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
692 type = eSymbolTypeStatic;
693 break;
694
695 case N_LCSYM: // .lcomm symbol: name,,n_sect,type,address
696 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
697 type = eSymbolTypeCommonBlock;
698 break;
699
700 case N_BNSYM:
701 // We use the current number of symbols in the symbol table in lieu of
702 // using nlist_idx in case we ever start trimming entries out
703 if (minimize)
704 {
705 // Skip these if we want minimal symbol tables
706 add_nlist = false;
707 }
708 else
709 {
710 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
711 N_NSYM_indexes.push_back(sym_idx);
712 type = eSymbolTypeScopeBegin;
713 }
714 break;
715
716 case N_ENSYM:
717 // Set the size of the N_BNSYM to the terminating index of this N_ENSYM
718 // so that we can always skip the entire symbol if we need to navigate
719 // more quickly at the source level when parsing STABS
720 if (minimize)
721 {
722 // Skip these if we want minimal symbol tables
723 add_nlist = false;
724 }
725 else
726 {
727 if ( !N_NSYM_indexes.empty() )
728 {
729 symbol_ptr = symtab->SymbolAtIndex(N_NSYM_indexes.back());
730 symbol_ptr->SetByteSize(sym_idx + 1);
731 symbol_ptr->SetSizeIsSibling(true);
732 N_NSYM_indexes.pop_back();
733 }
734 type = eSymbolTypeScopeEnd;
735 }
736 break;
737
738
739 case N_OPT: // emitted with gcc2_compiled and in gcc source
740 type = eSymbolTypeCompiler;
741 break;
742
743 case N_RSYM: // register sym: name,,NO_SECT,type,register
744 type = eSymbolTypeVariable;
745 break;
746
747 case N_SLINE: // src line: 0,,n_sect,linenumber,address
748 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
749 type = eSymbolTypeLineEntry;
750 break;
751
752 case N_SSYM: // structure elt: name,,NO_SECT,type,struct_offset
753 type = eSymbolTypeVariableType;
754 break;
755
756 case N_SO:
757 type = eSymbolTypeSourceFile;
758 if (symbol_name == NULL)
759 {
760 if (N_SO_index == UINT_MAX)
761 {
762 // Skip the extra blank N_SO entries that happen when the entire
763 // path is contained in the second consecutive N_SO STAB.
764 if (minimize)
765 add_nlist = false;
766 }
767 else
768 {
769 // Set the size of the N_SO to the terminating index of this N_SO
770 // so that we can always skip the entire N_SO if we need to navigate
771 // more quickly at the source level when parsing STABS
772 symbol_ptr = symtab->SymbolAtIndex(N_SO_index);
773 symbol_ptr->SetByteSize(sym_idx + 1);
774 symbol_ptr->SetSizeIsSibling(true);
775 }
776 N_NSYM_indexes.clear();
777 N_INCL_indexes.clear();
778 N_BRAC_indexes.clear();
779 N_COMM_indexes.clear();
780 N_FUN_indexes.clear();
781 N_SO_index = UINT_MAX;
782 }
783 else if (symbol_name[0] == '/')
784 {
785 // We use the current number of symbols in the symbol table in lieu of
786 // using nlist_idx in case we ever start trimming entries out
787 N_SO_index = sym_idx;
788 }
789 break;
790
791 case N_OSO: // object file name: name,,0,0,st_mtime
792 type = eSymbolTypeObjectFile;
793 break;
794
795 case N_LSYM: // local sym: name,,NO_SECT,type,offset
796 type = eSymbolTypeLocal;
797 break;
798
799 //----------------------------------------------------------------------
800 // INCL scopes
801 //----------------------------------------------------------------------
802 case N_BINCL: // include file beginning: name,,NO_SECT,0,sum
803 // We use the current number of symbols in the symbol table in lieu of
804 // using nlist_idx in case we ever start trimming entries out
805 N_INCL_indexes.push_back(sym_idx);
806 type = eSymbolTypeScopeBegin;
807 break;
808 case N_EINCL: // include file end: name,,NO_SECT,0,0
809
810 // Set the size of the N_BINCL to the terminating index of this N_EINCL
811 // so that we can always skip the entire symbol if we need to navigate
812 // more quickly at the source level when parsing STABS
813 if ( !N_INCL_indexes.empty() )
814 {
815 symbol_ptr = symtab->SymbolAtIndex(N_INCL_indexes.back());
816 symbol_ptr->SetByteSize(sym_idx + 1);
817 symbol_ptr->SetSizeIsSibling(true);
818 N_INCL_indexes.pop_back();
819 }
820 type = eSymbolTypeScopeEnd;
821 break;
822
823 case N_SOL: // #included file name: name,,n_sect,0,address
824 type = eSymbolTypeHeaderFile;
825 break;
826
827 case N_PARAMS: // compiler parameters: name,,NO_SECT,0,0
828 type = eSymbolTypeCompiler;
829 break;
830
831 case N_VERSION: // compiler version: name,,NO_SECT,0,0
832 type = eSymbolTypeCompiler;
833 break;
834
835 case N_OLEVEL: // compiler -O level: name,,NO_SECT,0,0
836 type = eSymbolTypeCompiler;
837 break;
838
839 case N_PSYM: // parameter: name,,NO_SECT,type,offset
840 type = eSymbolTypeVariable;
841 break;
842
843 case N_ENTRY: // alternate entry: name,,n_sect,linenumber,address
844 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
845 type = eSymbolTypeLineEntry;
846 break;
847
848 //----------------------------------------------------------------------
849 // Left and Right Braces
850 //----------------------------------------------------------------------
851 case N_LBRAC: // left bracket: 0,,NO_SECT,nesting level,address
852 // We use the current number of symbols in the symbol table in lieu of
853 // using nlist_idx in case we ever start trimming entries out
854 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
855 N_BRAC_indexes.push_back(sym_idx);
856 type = eSymbolTypeScopeBegin;
857 break;
858
859 case N_RBRAC: // right bracket: 0,,NO_SECT,nesting level,address
860 // Set the size of the N_LBRAC to the terminating index of this N_RBRAC
861 // so that we can always skip the entire symbol if we need to navigate
862 // more quickly at the source level when parsing STABS
863 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
864 if ( !N_BRAC_indexes.empty() )
865 {
866 symbol_ptr = symtab->SymbolAtIndex(N_BRAC_indexes.back());
867 symbol_ptr->SetByteSize(sym_idx + 1);
868 symbol_ptr->SetSizeIsSibling(true);
869 N_BRAC_indexes.pop_back();
870 }
871 type = eSymbolTypeScopeEnd;
872 break;
873
874 case N_EXCL: // deleted include file: name,,NO_SECT,0,sum
875 type = eSymbolTypeHeaderFile;
876 break;
877
878 //----------------------------------------------------------------------
879 // COMM scopes
880 //----------------------------------------------------------------------
881 case N_BCOMM: // begin common: name,,NO_SECT,0,0
882 // We use the current number of symbols in the symbol table in lieu of
883 // using nlist_idx in case we ever start trimming entries out
884 type = eSymbolTypeScopeBegin;
885 N_COMM_indexes.push_back(sym_idx);
886 break;
887
888 case N_ECOML: // end common (local name): 0,,n_sect,0,address
889 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
890 // Fall through
891
892 case N_ECOMM: // end common: name,,n_sect,0,0
893 // Set the size of the N_BCOMM to the terminating index of this N_ECOMM/N_ECOML
894 // so that we can always skip the entire symbol if we need to navigate
895 // more quickly at the source level when parsing STABS
896 if ( !N_COMM_indexes.empty() )
897 {
898 symbol_ptr = symtab->SymbolAtIndex(N_COMM_indexes.back());
899 symbol_ptr->SetByteSize(sym_idx + 1);
900 symbol_ptr->SetSizeIsSibling(true);
901 N_COMM_indexes.pop_back();
902 }
903 type = eSymbolTypeScopeEnd;
904 break;
905
906 case N_LENG: // second stab entry with length information
907 type = eSymbolTypeAdditional;
908 break;
909
910 default: break;
911 }
912 }
913 else
914 {
915 //uint8_t n_pext = N_PEXT & nlist.n_type;
916 uint8_t n_type = N_TYPE & nlist.n_type;
917 sym[sym_idx].SetExternal((N_EXT & nlist.n_type) != 0);
918
919 if (symbol_name && ::strstr (symbol_name, ".objc") == symbol_name)
920 {
921 type = eSymbolTypeRuntime;
922 }
923 else
924 {
925 switch (n_type)
926 {
927 case N_INDR: // Fall through
928 case N_PBUD: // Fall through
929 case N_UNDF:
930 type = eSymbolTypeExtern;
931 break;
932
933 case N_ABS:
934 type = eSymbolTypeAbsolute;
935 break;
936
937 case N_SECT:
938 symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value);
939
940 assert(symbol_section != NULL);
941 if (TEXT_eh_frame_sectID == nlist.n_sect)
942 {
943 type = eSymbolTypeException;
944 }
945 else
946 {
947 uint32_t section_type = symbol_section->GetAllFlagBits() & SECTION_TYPE;
948
949 switch (section_type)
950 {
951 case S_REGULAR: break; // regular section
952 //case S_ZEROFILL: type = eSymbolTypeData; break; // zero fill on demand section
953 case S_CSTRING_LITERALS: type = eSymbolTypeData; break; // section with only literal C strings
954 case S_4BYTE_LITERALS: type = eSymbolTypeData; break; // section with only 4 byte literals
955 case S_8BYTE_LITERALS: type = eSymbolTypeData; break; // section with only 8 byte literals
956 case S_LITERAL_POINTERS: type = eSymbolTypeTrampoline; break; // section with only pointers to literals
957 case S_NON_LAZY_SYMBOL_POINTERS: type = eSymbolTypeTrampoline; break; // section with only non-lazy symbol pointers
958 case S_LAZY_SYMBOL_POINTERS: type = eSymbolTypeTrampoline; break; // section with only lazy symbol pointers
959 case S_SYMBOL_STUBS: type = eSymbolTypeTrampoline; break; // section with only symbol stubs, byte size of stub in the reserved2 field
960 case S_MOD_INIT_FUNC_POINTERS: type = eSymbolTypeCode; break; // section with only function pointers for initialization
961 case S_MOD_TERM_FUNC_POINTERS: type = eSymbolTypeCode; break; // section with only function pointers for termination
962 //case S_COALESCED: type = eSymbolType; break; // section contains symbols that are to be coalesced
963 //case S_GB_ZEROFILL: type = eSymbolTypeData; break; // zero fill on demand section (that can be larger than 4 gigabytes)
964 case S_INTERPOSING: type = eSymbolTypeTrampoline; break; // section with only pairs of function pointers for interposing
965 case S_16BYTE_LITERALS: type = eSymbolTypeData; break; // section with only 16 byte literals
966 case S_DTRACE_DOF: type = eSymbolTypeInstrumentation; break;
967 case S_LAZY_DYLIB_SYMBOL_POINTERS: type = eSymbolTypeTrampoline; break;
968 default: break;
969 }
970
971 if (type == eSymbolTypeInvalid)
972 {
973 const char *symbol_sect_name = symbol_section->GetName().AsCString();
974 if (symbol_section->IsDescendant (text_section_sp.get()))
975 {
976 if (symbol_section->IsClear(S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE | S_ATTR_SOME_INSTRUCTIONS))
977 type = eSymbolTypeData;
978 else
979 type = eSymbolTypeCode;
980 }
981 else
982 if (symbol_section->IsDescendant(data_section_sp.get()))
983 {
984 if (symbol_sect_name && ::strstr (symbol_sect_name, "__objc") == symbol_sect_name)
985 {
986 type = eSymbolTypeRuntime;
987 }
988 else
989 if (symbol_sect_name && ::strstr (symbol_sect_name, "__gcc_except_tab") == symbol_sect_name)
990 {
991 type = eSymbolTypeException;
992 }
993 else
994 {
995 type = eSymbolTypeData;
996 }
997 }
998 else
999 if (symbol_sect_name && ::strstr (symbol_sect_name, "__IMPORT") == symbol_sect_name)
1000 {
1001 type = eSymbolTypeTrampoline;
1002 }
1003 else
1004 if (symbol_section->IsDescendant(objc_section_sp.get()))
1005 {
1006 type = eSymbolTypeRuntime;
1007 }
1008 }
1009 }
1010 break;
1011 }
1012 }
1013 }
1014
1015 if (add_nlist)
1016 {
1017 bool symbol_name_is_mangled = false;
1018 if (symbol_name && symbol_name[0] == '_')
1019 {
1020 symbol_name_is_mangled = symbol_name[1] == '_';
1021 symbol_name++; // Skip the leading underscore
1022 }
1023 uint64_t symbol_value = nlist.n_value;
1024 if (symbol_section != NULL)
1025 symbol_value -= symbol_section->GetFileAddress();
1026
1027 sym[sym_idx].SetID (nlist_idx);
1028 sym[sym_idx].SetType (type);
1029 if (symbol_name)
1030 sym[sym_idx].GetMangled().SetValue(symbol_name, symbol_name_is_mangled);
1031 sym[sym_idx].GetAddressRangeRef().GetBaseAddress().SetSection (symbol_section);
1032 sym[sym_idx].GetAddressRangeRef().GetBaseAddress().SetOffset (symbol_value);
1033 sym[sym_idx].SetFlags (nlist.n_type << 16 | nlist.n_desc);
1034
1035 ++sym_idx;
1036 }
1037 else
1038 {
1039 sym[sym_idx].Clear();
1040 }
1041
1042 }
1043
1044
1045 // STAB N_GSYM entries end up having a symbol type eSymbolTypeGlobal and when the symbol value
1046 // is zero, the address of the global ends up being in a non-STAB entry. Try and fix up all
1047 // such entries by figuring out what the address for the global is by looking up this non-STAB
1048 // entry and copying the value into the debug symbol's value to save us the hassle in the
1049 // debug symbol parser.
1050
1051 Symbol *global_symbol = NULL;
1052 for (nlist_idx = 0;
1053 nlist_idx < symtab_load_command.nsyms && (global_symbol = symtab->FindSymbolWithType(eSymbolTypeGlobal, nlist_idx)) != NULL;
1054 nlist_idx++)
1055 {
1056 if (global_symbol->GetValue().GetFileAddress() == 0)
1057 {
1058 std::vector<uint32_t> indexes;
1059 if (symtab->AppendSymbolIndexesWithName(global_symbol->GetMangled().GetName(), indexes) > 0)
1060 {
1061 std::vector<uint32_t>::const_iterator pos;
1062 std::vector<uint32_t>::const_iterator end = indexes.end();
1063 for (pos = indexes.begin(); pos != end; ++pos)
1064 {
1065 symbol_ptr = symtab->SymbolAtIndex(*pos);
1066 if (symbol_ptr != global_symbol && symbol_ptr->IsDebug() == false)
1067 {
1068 global_symbol->SetValue(symbol_ptr->GetValue());
1069 break;
1070 }
1071 }
1072 }
1073 }
1074 }
1075 // Now synthesize indirect symbols
1076 if (m_dysymtab.nindirectsyms != 0)
1077 {
1078 DataBufferSP indirect_symbol_indexes_sp(m_file.ReadFileContents(m_offset + m_dysymtab.indirectsymoff, m_dysymtab.nindirectsyms * 4));
1079
1080 if (indirect_symbol_indexes_sp && indirect_symbol_indexes_sp->GetByteSize())
1081 {
1082 DataExtractor indirect_symbol_index_data (indirect_symbol_indexes_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
1083
1084 for (uint32_t sect_idx = 1; sect_idx < m_mach_sections.size(); ++sect_idx)
1085 {
1086 if ((m_mach_sections[sect_idx].flags & SECTION_TYPE) == S_SYMBOL_STUBS)
1087 {
1088 uint32_t symbol_stub_byte_size = m_mach_sections[sect_idx].reserved2;
1089 if (symbol_stub_byte_size == 0)
1090 continue;
1091
1092 const uint32_t num_symbol_stubs = m_mach_sections[sect_idx].size / symbol_stub_byte_size;
1093
1094 if (num_symbol_stubs == 0)
1095 continue;
1096
1097 const uint32_t symbol_stub_index_offset = m_mach_sections[sect_idx].reserved1;
1098 uint32_t stub_sym_id = symtab_load_command.nsyms;
1099 for (uint32_t stub_idx = 0; stub_idx < num_symbol_stubs; ++stub_idx)
1100 {
1101 const uint32_t symbol_stub_index = symbol_stub_index_offset + stub_idx;
1102 const lldb::addr_t symbol_stub_addr = m_mach_sections[sect_idx].addr + (stub_idx * symbol_stub_byte_size);
1103 uint32_t symbol_stub_offset = symbol_stub_index * 4;
1104 if (indirect_symbol_index_data.ValidOffsetForDataOfSize(symbol_stub_offset, 4))
1105 {
1106 const uint32_t symbol_index = indirect_symbol_index_data.GetU32 (&symbol_stub_offset);
1107
1108 Symbol *stub_symbol = symtab->SymbolAtIndex(symbol_index);
1109 if (stub_symbol)
1110 {
1111 Address so_addr(symbol_stub_addr, section_list);
1112
1113 if (stub_symbol->GetType() == eSymbolTypeExtern)
1114 {
1115 // Change the external symbol into a trampoline that makes sense
1116 // These symbols were N_UNDF N_EXT, and are useless to us, so we
1117 // can re-use them so we don't have to make up a synthetic symbol
1118 // for no good reason.
1119 stub_symbol->SetType (eSymbolTypeTrampoline);
1120 stub_symbol->SetExternal (false);
1121 stub_symbol->GetAddressRangeRef().GetBaseAddress() = so_addr;
1122 stub_symbol->GetAddressRangeRef().SetByteSize (symbol_stub_byte_size);
1123 }
1124 else
1125 {
1126 // Make a synthetic symbol to describe the trampoline stub
1127 if (sym_idx >= num_syms)
1128 {
1129 sym = symtab->Resize (num_syms + 16);
1130 num_syms = symtab->GetNumSymbols();
1131 }
1132 sym[sym_idx].SetID (stub_sym_id++);
1133 sym[sym_idx].GetMangled() = stub_symbol->GetMangled();
1134 sym[sym_idx].SetType (eSymbolTypeTrampoline);
1135 sym[sym_idx].SetIsSynthetic (true);
1136 sym[sym_idx].GetAddressRangeRef().GetBaseAddress() = so_addr;
1137 sym[sym_idx].GetAddressRangeRef().SetByteSize (symbol_stub_byte_size);
1138 ++sym_idx;
1139 }
1140 }
1141 }
1142 }
1143 }
1144 }
1145 }
1146 }
1147
1148 if (sym_idx != symtab->GetNumSymbols())
1149 symtab->Resize (sym_idx);
1150
1151 return symtab->GetNumSymbols();
1152 }
1153 }
1154 offset = cmd_offset + symtab_load_command.cmdsize;
1155 }
1156 return 0;
1157}
1158
1159
1160void
1161ObjectFileMachO::Dump (Stream *s)
1162{
1163 lldb_private::Mutex::Locker locker(m_mutex);
1164 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
1165 s->Indent();
1166 if (m_header.magic == MH_MAGIC_64 || m_header.magic == MH_CIGAM_64)
1167 s->PutCString("ObjectFileMachO64");
1168 else
1169 s->PutCString("ObjectFileMachO32");
1170
Greg Clayton41f92322010-06-11 03:25:34 +00001171 ArchSpec header_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001172
1173 *s << ", file = '" << m_file << "', arch = " << header_arch.AsCString() << "\n";
1174
1175 if (m_sections_ap.get())
1176 m_sections_ap->Dump(s, NULL, true);
1177
1178 if (m_symtab_ap.get())
1179 m_symtab_ap->Dump(s, NULL);
1180}
1181
1182
1183bool
1184ObjectFileMachO::GetUUID (UUID* uuid)
1185{
1186 lldb_private::Mutex::Locker locker(m_mutex);
1187 struct uuid_command load_cmd;
1188 uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
1189 uint32_t i;
1190 for (i=0; i<m_header.ncmds; ++i)
1191 {
1192 const uint32_t cmd_offset = offset;
1193 if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
1194 break;
1195
1196 if (load_cmd.cmd == LC_UUID)
1197 {
1198 const uint8_t *uuid_bytes = m_data.PeekData(offset, 16);
1199 if (uuid_bytes)
1200 {
1201 uuid->SetBytes (uuid_bytes);
1202 return true;
1203 }
1204 return false;
1205 }
1206 offset = cmd_offset + load_cmd.cmdsize;
1207 }
1208 return false;
1209}
1210
1211
1212uint32_t
1213ObjectFileMachO::GetDependentModules (FileSpecList& files)
1214{
1215 lldb_private::Mutex::Locker locker(m_mutex);
1216 struct load_command load_cmd;
1217 uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
1218 uint32_t count = 0;
1219 uint32_t i;
1220 for (i=0; i<m_header.ncmds; ++i)
1221 {
1222 const uint32_t cmd_offset = offset;
1223 if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
1224 break;
1225
1226 switch (load_cmd.cmd)
1227 {
1228 case LC_LOAD_DYLIB:
1229 case LC_LOAD_WEAK_DYLIB:
1230 case LC_REEXPORT_DYLIB:
1231 case LC_LOAD_DYLINKER:
1232 case LC_LOADFVMLIB:
1233 {
1234 uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
1235 const char *path = m_data.PeekCStr(name_offset);
1236 // Skip any path that starts with '@' since these are usually:
1237 // @executable_path/.../file
1238 // @rpath/.../file
1239 if (path && path[0] != '@')
1240 {
1241 FileSpec file_spec(path);
1242 if (files.AppendIfUnique(file_spec))
1243 count++;
1244 }
1245 }
1246 break;
1247
1248 default:
1249 break;
1250 }
1251 offset = cmd_offset + load_cmd.cmdsize;
1252 }
1253 return count;
1254}
1255
1256bool
1257ObjectFileMachO::GetTargetTriple (ConstString &target_triple)
1258{
1259 lldb_private::Mutex::Locker locker(m_mutex);
1260 std::string triple(GetModule()->GetArchitecture().AsCString());
1261 triple += "-apple-darwin";
1262 target_triple.SetCString(triple.c_str());
1263 if (target_triple)
1264 return true;
1265 return false;
1266}
1267
1268
1269//------------------------------------------------------------------
1270// PluginInterface protocol
1271//------------------------------------------------------------------
1272const char *
1273ObjectFileMachO::GetPluginName()
1274{
1275 return "ObjectFileMachO";
1276}
1277
1278const char *
1279ObjectFileMachO::GetShortPluginName()
1280{
1281 return GetPluginNameStatic();
1282}
1283
1284uint32_t
1285ObjectFileMachO::GetPluginVersion()
1286{
1287 return 1;
1288}
1289
1290void
1291ObjectFileMachO::GetPluginCommandHelp (const char *command, Stream *strm)
1292{
1293}
1294
1295Error
1296ObjectFileMachO::ExecutePluginCommand (Args &command, Stream *strm)
1297{
1298 Error error;
1299 error.SetErrorString("No plug-in command are currently supported.");
1300 return error;
1301}
1302
1303Log *
1304ObjectFileMachO::EnablePluginLogging (Stream *strm, Args &command)
1305{
1306 return NULL;
1307}
1308
1309
1310
1311