Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/debuginfo.h" | 5 #include "vm/debuginfo.h" |
| 6 | 6 |
| 7 #include "platform/utils.h" | |
| 8 #include "vm/gdbjit_android.h" | |
| 9 #include "vm/os.h" | |
| 10 #include "vm/thread.h" | |
| 7 | 11 |
| 8 namespace dart { | 12 namespace dart { |
| 9 | 13 |
| 14 // ----------------------------------------------------------------------------- | |
|
cshapiro
2012/08/14 22:18:26
Can you move this into an elfgen.h which is includ
jackpal
2012/08/15 01:29:48
Done.
| |
| 15 // Implementation of ElfGen | |
| 16 // | |
| 17 // Specification documents: | |
| 18 // http://refspecs.freestandards.org | |
| 19 // | |
| 20 // ELF generic ABI: | |
| 21 // http://refspecs.freestandards.org/elf/gabi4+/contents.html | |
| 22 // ELF processor-specific supplement for X86_64: | |
| 23 // http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf | |
| 24 // DWARF 2.0: | |
| 25 // http://refspecs.freestandards.org/dwarf/dwarf-2.0.0.pdf | |
| 26 | |
| 27 // Forward declarations. | |
| 28 class File; | |
| 29 | |
| 30 // ElfGen is used to generate minimal ELF information containing code, symbols, | |
| 31 // and line numbers for generated code in the dart VM. This information is | |
| 32 // used in two ways: | |
| 33 // - it is used to generate in-memory ELF information which is then | |
| 34 // registered with gdb using the JIT interface. | |
| 35 // - it is also used to generate a file with the ELF information. This file | |
| 36 // is not executed, but read by pprof to analyze Dart programs. | |
| 37 | |
| 38 class ElfGen { | |
| 39 public: | |
| 40 ElfGen(); | |
| 41 ~ElfGen(); | |
| 42 | |
| 43 // Add the code starting at pc. | |
| 44 void AddCode(uword pc, intptr_t size); | |
| 45 | |
| 46 // Add symbol information for a region (includes the start and end symbol), | |
| 47 // does not add the actual code. | |
| 48 void AddCodeRegion(const char* name, uword pc, intptr_t size); | |
| 49 | |
| 50 // Add specified symbol information, does not add the actual code. | |
| 51 int AddFunction(const char* name, uword pc, intptr_t size); | |
| 52 | |
| 53 // Write out all the Elf information using the specified handle. | |
| 54 bool WriteToFile(File* handle); | |
| 55 bool WriteToMemory(DebugInfo::ByteBuffer* region); | |
| 56 | |
| 57 // Register this generated section with GDB using the JIT interface. | |
| 58 static void RegisterSectionWithGDB(const char* name, | |
| 59 uword entry_point, | |
| 60 intptr_t size); | |
| 61 | |
| 62 // Unregister all generated section from GDB. | |
| 63 static void UnregisterAllSectionsWithGDB(); | |
| 64 | |
| 65 private: | |
| 66 // ELF helpers | |
| 67 typedef int (*OutputWriter)(void* handle, | |
| 68 const DebugInfo::ByteBuffer& section); | |
| 69 typedef void (*OutputPadder)(void* handle, int padding_size); | |
| 70 | |
| 71 int AddString(DebugInfo::ByteBuffer* buf, const char* str); | |
| 72 int AddSectionName(const char* str); | |
| 73 int AddName(const char* str); | |
| 74 void AddELFHeader(int shoff); | |
| 75 void AddSectionHeader(int section, int offset); | |
| 76 int PadSection(DebugInfo::ByteBuffer* section, int offset, int alignment); | |
| 77 bool WriteOutput(void* handle, OutputWriter writer, OutputPadder padder); | |
| 78 | |
| 79 uword text_vma_; // text section vma | |
| 80 intptr_t text_size_; // text section size | |
| 81 int text_padding_; // padding preceding text section | |
| 82 | |
| 83 static const int kNumSections = 5; // we generate 5 sections | |
| 84 int section_name_[kNumSections]; // array of section name indices | |
| 85 DebugInfo::ByteBuffer section_buf_[kNumSections]; // array of section buffers | |
| 86 DebugInfo::ByteBuffer header_; // ELF header buffer | |
| 87 DebugInfo::ByteBuffer sheaders_; // section header table buffer | |
| 88 DebugInfo::ByteBuffer lineprog_; // line statement program, part of | |
| 89 // '.debug_line' section | |
| 90 | |
| 91 // current state of the DWARF line info generator | |
| 92 uintptr_t cur_addr_; // current pc | |
| 93 int map_offset_; | |
| 94 uword map_begin_; | |
| 95 uword map_end_; | |
| 96 | |
| 97 Mutex lock_; | |
| 98 }; | |
| 99 | |
| 100 | |
| 101 enum { | |
| 102 // Various constant sizes for ELF files. | |
| 103 kAddrSize = sizeof(uword), | |
| 104 kPageSize = 4*1024, // Memory mapping page size. | |
| 105 kTextAlign = 16, | |
| 106 kELFHeaderSize = 40 + 3*kAddrSize, | |
| 107 kProgramHeaderEntrySize = 8 + 6*kAddrSize, | |
| 108 kSectionHeaderEntrySize = 16 + 6*kAddrSize, | |
| 109 kSymbolSize = 8 + 2*kAddrSize, | |
| 110 | |
| 111 // Our own layout of sections. | |
| 112 kUndef = 0, // Undefined section. | |
| 113 kText, // Text section. | |
| 114 kShStrtab, // Section header string table. | |
| 115 kStrtab, // String table. | |
| 116 kSymtab, // Symbol table. | |
| 117 kNumSections, // Num of section header entries in section header table. | |
| 118 | |
| 119 // Various ELF constants. | |
| 120 kELFCLASS32 = 1, | |
| 121 kELFCLASS64 = 2, | |
| 122 kELFDATA2LSB = 1, | |
| 123 kELFDATA2MSB = 2, | |
| 124 kEM_386 = 3, | |
| 125 kEM_ARM = 40, | |
| 126 kEM_X86_64 = 62, | |
| 127 kEV_CURRENT = 1, | |
| 128 kET_EXEC = 2, // not used | |
| 129 kET_DYN = 3, | |
| 130 kSHT_PROGBITS = 1, | |
| 131 kSHT_SYMTAB = 2, | |
| 132 kSHT_STRTAB = 3, | |
| 133 kSHF_WRITE = 1, // not used | |
| 134 kSHF_ALLOC = 2, | |
| 135 kSHF_EXECINSTR = 4, | |
| 136 kSTB_LOCAL = 0, | |
| 137 kSTB_EXPORTED = 1, | |
| 138 kSTT_FUNC = 2, | |
| 139 }; | |
| 140 | |
| 141 | |
| 142 // ELF and DWARF constants. | |
| 143 static const char* kEI_MAG0_MAG3 = "\177ELF"; | |
| 144 static const uint8_t kSpecialOpcodeLengths[] = { 0, 1, 1, 1, 1, 0, 0, 0, 1 }; | |
| 145 | |
| 146 | |
| 147 // Section attributes. | |
| 148 // The field names correspond to the field names of Elf32_Shdr and Elf64_Shdr. | |
| 149 static const struct { | |
| 150 // Section header index (only used to check correct section order). | |
| 151 int shndx; | |
| 152 const char* name; // sh_name will be the index of name inserted in shstrtab. | |
| 153 int sh_type; | |
| 154 int sh_flags; | |
| 155 int sh_link; | |
| 156 int sh_addralign; | |
| 157 int sh_entsize; | |
| 158 } section_attr[kNumSections + 1] = { | |
| 159 { kUndef, "", 0, 0, | |
| 160 0, 0, 0 }, | |
| 161 { kText, ".text", kSHT_PROGBITS, kSHF_ALLOC|kSHF_EXECINSTR, | |
| 162 0, kTextAlign, 0 }, | |
| 163 { kShStrtab, ".shstrtab", kSHT_STRTAB, 0, | |
| 164 0, 1, 0 }, | |
| 165 { kStrtab, ".strtab", kSHT_STRTAB, 0, | |
| 166 0, 1, 0 }, | |
| 167 { kSymtab, ".symtab", kSHT_SYMTAB, 0, | |
| 168 kStrtab, kAddrSize, kSymbolSize }, | |
| 169 // Sentinel to pad the last section | |
| 170 // for proper alignment of section header table. | |
| 171 { 0, "", 0, 0, | |
| 172 0, kAddrSize, 0 } | |
| 173 }; | |
| 174 | |
| 175 | |
| 176 // Convenience function aligning an integer. | |
| 177 static inline uintptr_t Align(uintptr_t x, intptr_t size) { | |
| 178 // size is a power of 2 | |
| 179 ASSERT((size & (size-1)) == 0); | |
| 180 return (x + (size-1)) & ~(size-1); | |
| 181 } | |
| 182 | |
| 183 | |
| 184 // Convenience function writing a single byte to a ByteBuffer. | |
| 185 static inline void WriteByte(DebugInfo::ByteBuffer* buf, uint8_t byte) { | |
| 186 buf->Add(byte); | |
| 187 } | |
| 188 | |
| 189 | |
| 190 // Convenience function writing an unsigned native word to a ByteBuffer. | |
| 191 // The word is 32-bit wide in 32-bit mode and 64-bit wide in 64-bit mode. | |
| 192 static inline void WriteWord(DebugInfo::ByteBuffer* buf, uword word) { | |
| 193 uint8_t* p = reinterpret_cast<uint8_t*>(&word); | |
| 194 for (size_t i = 0; i < sizeof(word); i++) { | |
| 195 buf->Add(p[i]); | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 static inline void WriteInt(DebugInfo::ByteBuffer* buf, int word) { | |
| 200 uint8_t* p = reinterpret_cast<uint8_t*>(&word); | |
| 201 for (size_t i = 0; i < sizeof(word); i++) { | |
| 202 buf->Add(p[i]); | |
| 203 } | |
| 204 } | |
| 205 | |
| 206 static inline void WriteShort(DebugInfo::ByteBuffer* buf, uint16_t word) { | |
| 207 uint8_t* p = reinterpret_cast<uint8_t*>(&word); | |
| 208 for (size_t i = 0; i < sizeof(word); i++) { | |
| 209 buf->Add(p[i]); | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 static inline void WriteString(DebugInfo::ByteBuffer* buf, const char* str) { | |
| 214 for (size_t i = 0; i < strlen(str); i++) { | |
| 215 buf->Add(static_cast<uint8_t>(str[i])); | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 static inline void Write(DebugInfo::ByteBuffer* buf, | |
| 220 const void* mem, | |
| 221 int length) { | |
| 222 const uint8_t* p = reinterpret_cast<const uint8_t*>(mem); | |
| 223 for (int i = 0; i < length; i++) { | |
| 224 buf->Add(p[i]); | |
| 225 } | |
| 226 } | |
| 227 | |
| 228 | |
| 229 // Write given section to file and return written size. | |
| 230 static int WriteSectionToFile(void* handle, | |
| 231 const DebugInfo::ByteBuffer& section) { | |
| 232 #if 0 | |
| 233 File* fp = reinterpret_cast<File*>(handle); | |
| 234 int size = section.size(); | |
| 235 fp->WriteFully(section.data(), size); | |
| 236 return size; | |
| 237 #else | |
| 238 return 0; | |
| 239 #endif | |
| 240 } | |
| 241 | |
| 242 | |
| 243 // Pad output file to specified padding size. | |
| 244 static void PadFile(void* handle, int padding_size) { | |
| 245 #if 0 | |
| 246 File* fp = reinterpret_cast<File*>(handle); | |
| 247 for (int i = 0; i < padding_size; i++) { | |
| 248 fp->WriteFully("", 1); | |
| 249 } | |
| 250 #endif | |
| 251 } | |
| 252 | |
| 253 | |
| 254 // Write given section to specified memory region and return written size. | |
| 255 static int WriteSectionToMemory(void* handle, | |
| 256 const DebugInfo::ByteBuffer& section) { | |
| 257 DebugInfo::ByteBuffer* buffer = | |
| 258 reinterpret_cast<DebugInfo::ByteBuffer*>(handle); | |
| 259 int size = section.size(); | |
| 260 for (int i = 0; i < size; i++) { | |
| 261 buffer->Add(static_cast<uint8_t>(section.data()[i])); | |
| 262 } | |
| 263 return size; | |
| 264 } | |
| 265 | |
| 266 | |
| 267 // Pad memory to specified padding size. | |
| 268 static void PadMemory(void* handle, int padding_size) { | |
| 269 DebugInfo::ByteBuffer* buffer = | |
| 270 reinterpret_cast<DebugInfo::ByteBuffer*>(handle); | |
| 271 for (int i = 0; i < padding_size; i++) { | |
| 272 buffer->Add(static_cast<uint8_t>(0)); | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 | |
| 277 // Constructor | |
| 278 ElfGen::ElfGen() | |
| 279 : text_vma_(0), text_size_(0), text_padding_(0), map_offset_(0), lock_() { | |
| 280 for (int i = 0; i < kNumSections; i++) { | |
| 281 ASSERT(section_attr[i].shndx == i); // Verify layout of sections. | |
| 282 section_name_[i] = AddSectionName(section_attr[i].name); | |
| 283 } | |
| 284 // Section header string table always starts with an empty string, which is | |
| 285 // the name of the kUndef section. | |
| 286 ASSERT((section_attr[0].name[0] == '\0') && (section_name_[0] == 0)); | |
| 287 | |
| 288 // String table always starts with an empty string. | |
| 289 AddName(""); | |
| 290 ASSERT(section_buf_[kStrtab].size() == 1); | |
| 291 | |
| 292 // Symbol at index 0 in symtab is always STN_UNDEF (all zero): | |
| 293 DebugInfo::ByteBuffer* symtab = §ion_buf_[kSymtab]; | |
| 294 while (symtab->size() < kSymbolSize) { | |
| 295 WriteInt(symtab, 0); | |
| 296 } | |
| 297 ASSERT(symtab->size() == kSymbolSize); | |
| 298 } | |
| 299 | |
| 300 | |
| 301 // Destructor | |
| 302 ElfGen::~ElfGen() { | |
| 303 } | |
| 304 | |
| 305 | |
| 306 void ElfGen::AddCode(uword pc, intptr_t size) { | |
| 307 MutexLocker ml(&lock_); | |
| 308 text_vma_ = pc; | |
| 309 text_size_ = size; | |
| 310 // We pad the text section in the file to align absolute code addresses with | |
| 311 // corresponding file offsets as if the code had been loaded by memory | |
| 312 // mapping. | |
| 313 if (text_vma_ % kPageSize < kELFHeaderSize) { | |
| 314 text_padding_ = text_vma_ % kPageSize + kPageSize - kELFHeaderSize; | |
| 315 } else { | |
| 316 text_padding_ = text_vma_ % kPageSize - kELFHeaderSize; | |
| 317 } | |
| 318 | |
| 319 Write(§ion_buf_[kText], reinterpret_cast<void*>(pc), size); | |
| 320 // map_offset is the file offset of the first mapped page. | |
| 321 map_offset_ = (kELFHeaderSize + text_padding_)/kPageSize*kPageSize; | |
| 322 map_begin_ = Align(text_vma_ - kPageSize + 1, kPageSize); | |
| 323 map_end_ = Align(text_vma_ + size, kPageSize); | |
| 324 } | |
| 325 | |
| 326 | |
| 327 void ElfGen::AddCodeRegion(const char* name, uword pc, intptr_t size) { | |
| 328 MutexLocker ml(&lock_); | |
| 329 AddFunction(name, pc, size); | |
| 330 char end_name[256]; | |
| 331 OS::SNPrint(end_name, sizeof(end_name), "%s_end", name); | |
| 332 AddFunction(end_name, pc + size, 0); | |
| 333 } | |
| 334 | |
| 335 | |
| 336 int ElfGen::AddFunction(const char* name, uword pc, intptr_t size) { | |
| 337 ASSERT(text_vma_ != 0); // code must have been added | |
| 338 DebugInfo::ByteBuffer* symtab = §ion_buf_[kSymtab]; | |
| 339 const int beg = symtab->size(); | |
| 340 WriteInt(symtab, AddName(name)); // st_name | |
| 341 #if defined(TARGET_ARCH_X64) | |
| 342 WriteShort(symtab, (kSTB_LOCAL << 4) + kSTT_FUNC); // st_info + (st_other<<8) | |
| 343 WriteShort(symtab, kText); // st_shndx | |
| 344 #endif | |
| 345 WriteWord(symtab, pc); // st_value | |
| 346 WriteWord(symtab, size); // st_size | |
| 347 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | |
| 348 // st_info + (st_other<<8) | |
| 349 WriteShort(symtab, (kSTB_EXPORTED << 4) + kSTT_FUNC); | |
| 350 WriteShort(symtab, kText); // st_shndx | |
| 351 #endif | |
| 352 ASSERT(symtab->size() - beg == kSymbolSize); | |
| 353 return beg / kSymbolSize; // symbol index in symtab | |
| 354 } | |
| 355 | |
| 356 | |
| 357 bool ElfGen::WriteToFile(File* handle) { | |
| 358 return WriteOutput(handle, WriteSectionToFile, PadFile); | |
| 359 } | |
| 360 | |
| 361 | |
| 362 bool ElfGen::WriteToMemory(DebugInfo::ByteBuffer* region) { | |
| 363 return WriteOutput(region, WriteSectionToMemory, PadMemory); | |
| 364 } | |
| 365 | |
| 366 | |
| 367 int ElfGen::AddString(DebugInfo::ByteBuffer* buf, const char* str) { | |
| 368 const int str_index = buf->size(); | |
| 369 WriteString(buf, str); | |
| 370 WriteByte(buf, 0); // terminating '\0' | |
| 371 return str_index; | |
| 372 } | |
| 373 | |
| 374 | |
| 375 int ElfGen::AddSectionName(const char* str) { | |
| 376 return AddString(§ion_buf_[kShStrtab], str); | |
| 377 } | |
| 378 | |
| 379 | |
| 380 int ElfGen::AddName(const char* str) { | |
| 381 return AddString(§ion_buf_[kStrtab], str); | |
| 382 } | |
| 383 | |
| 384 | |
| 385 void ElfGen::AddELFHeader(int shoff) { | |
| 386 ASSERT(text_vma_ != 0); // Code must have been added. | |
| 387 Write(&header_, kEI_MAG0_MAG3, 4); // EI_MAG0..EI_MAG3 | |
| 388 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | |
| 389 WriteByte(&header_, kELFCLASS32); // EI_CLASS | |
| 390 #elif defined(TARGET_ARCH_X64) | |
| 391 WriteByte(&header_, kELFCLASS64); // EI_CLASS | |
| 392 #endif | |
| 393 WriteByte(&header_, kELFDATA2LSB); // EI_DATA | |
| 394 WriteByte(&header_, kEV_CURRENT); // EI_VERSION | |
| 395 WriteByte(&header_, 0); // EI_PAD | |
| 396 WriteInt(&header_, 0); // EI_PAD | |
| 397 WriteInt(&header_, 0); // EI_PAD | |
| 398 WriteShort(&header_, kET_DYN); // e_type, fake a shared object. | |
| 399 #if defined(TARGET_ARCH_IA32) | |
| 400 WriteShort(&header_, kEM_386); // e_machine | |
| 401 #elif defined(TARGET_ARCH_X64) | |
| 402 WriteShort(&header_, kEM_X86_64); // e_machine | |
| 403 #elif defined(TARGET_ARCH_ARM) | |
| 404 WriteShort(&header_, kEM_ARM); // e_machine | |
| 405 #endif | |
| 406 WriteInt(&header_, kEV_CURRENT); // e_version | |
| 407 WriteWord(&header_, 0); // e_entry: none | |
| 408 WriteWord(&header_, 0); // e_phoff: no program header table. | |
| 409 WriteWord(&header_, shoff); // e_shoff: section header table offset. | |
| 410 WriteInt(&header_, 0); // e_flags: no flags. | |
| 411 WriteShort(&header_, kELFHeaderSize); // e_ehsize: header size. | |
| 412 WriteShort(&header_, kProgramHeaderEntrySize); // e_phentsize | |
| 413 WriteShort(&header_, 0); // e_phnum: no entries program header table. | |
| 414 WriteShort(&header_, kSectionHeaderEntrySize); // e_shentsize | |
| 415 // e_shnum: number of section header entries. | |
| 416 WriteShort(&header_, kNumSections); | |
| 417 WriteShort(&header_, kShStrtab); // e_shstrndx: index of shstrtab. | |
| 418 ASSERT(header_.size() == kELFHeaderSize); | |
| 419 } | |
| 420 | |
| 421 | |
| 422 void ElfGen::AddSectionHeader(int section, int offset) { | |
| 423 WriteInt(&sheaders_, section_name_[section]); | |
| 424 WriteInt(&sheaders_, section_attr[section].sh_type); | |
| 425 WriteWord(&sheaders_, section_attr[section].sh_flags); | |
| 426 // sh_addr: abs addr | |
| 427 WriteWord(&sheaders_, (section == kText) ? text_vma_ : 0); | |
| 428 WriteWord(&sheaders_, offset); // sh_offset: section file offset. | |
| 429 WriteWord(&sheaders_, section_buf_[section].size()); | |
| 430 WriteInt(&sheaders_, section_attr[section].sh_link); | |
| 431 WriteInt(&sheaders_, 0); | |
| 432 WriteWord(&sheaders_, section_attr[section].sh_addralign); | |
| 433 WriteWord(&sheaders_, section_attr[section].sh_entsize); | |
| 434 ASSERT(sheaders_.size() == kSectionHeaderEntrySize * (section + 1)); | |
| 435 } | |
| 436 | |
| 437 | |
| 438 // Pads the given section with zero bytes for the given aligment, assuming the | |
| 439 // section starts at given file offset; returns file offset after padded | |
| 440 // section. | |
| 441 int ElfGen::PadSection(DebugInfo::ByteBuffer* section, | |
| 442 int offset, | |
| 443 int alignment) { | |
| 444 offset += section->size(); | |
| 445 int aligned_offset = Align(offset, alignment); | |
| 446 while (offset++ < aligned_offset) { | |
| 447 WriteByte(section, 0); // one byte padding. | |
| 448 } | |
| 449 return aligned_offset; | |
| 450 } | |
| 451 | |
| 452 | |
| 453 bool ElfGen::WriteOutput(void* handle, | |
| 454 OutputWriter writer, | |
| 455 OutputPadder padder) { | |
| 456 if (handle == NULL || writer == NULL || padder == NULL) { | |
| 457 return false; | |
| 458 } | |
| 459 | |
| 460 // Align all sections before writing the ELF header in order to calculate the | |
| 461 // file offset of the section header table, which is needed in the ELF header. | |
| 462 // Pad each section as required by the aligment constraint of the immediately | |
| 463 // following section, except the ELF header section, which requires special | |
| 464 // padding (text_padding_) to align the text_ section. | |
| 465 int offset = kELFHeaderSize + text_padding_; | |
| 466 for (int i = kText; i < kNumSections; i++) { | |
| 467 offset = PadSection(§ion_buf_[i], | |
| 468 offset, | |
| 469 section_attr[i+1].sh_addralign); | |
| 470 } | |
| 471 | |
| 472 const int shoff = offset; // Section header table offset. | |
| 473 | |
| 474 // Write elf header. | |
| 475 AddELFHeader(shoff); | |
| 476 offset = (*writer)(handle, header_); | |
| 477 | |
| 478 // Pad file before writing text section in order to align vma with file | |
| 479 // offset. | |
| 480 (*padder)(handle, text_padding_); | |
| 481 | |
| 482 offset += text_padding_; | |
| 483 ASSERT((text_vma_ - offset) % kPageSize == 0); | |
| 484 | |
| 485 // Section header at index 0 in section header table is always SHN_UNDEF: | |
| 486 for (int i = 0; i < kNumSections; i++) { | |
| 487 AddSectionHeader(i, offset); | |
| 488 offset += (*writer)(handle, section_buf_[i]); | |
| 489 } | |
| 490 // Write section header table. | |
| 491 ASSERT(offset == shoff); | |
| 492 offset += (*writer)(handle, sheaders_); | |
| 493 ASSERT(offset == shoff + kNumSections * kSectionHeaderEntrySize); | |
| 494 | |
| 495 return true; | |
| 496 } | |
| 497 | |
| 498 | |
| 10 DebugInfo::DebugInfo() { | 499 DebugInfo::DebugInfo() { |
| 11 handle_ = NULL; | 500 handle_ = reinterpret_cast<void*>(new ElfGen()); |
| 501 ASSERT(handle_ != NULL); | |
| 12 } | 502 } |
| 13 | 503 |
| 14 | 504 |
| 15 DebugInfo::~DebugInfo() { | 505 DebugInfo::~DebugInfo() { |
| 506 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); | |
| 507 delete elf_gen; | |
| 16 } | 508 } |
| 17 | 509 |
| 18 | 510 |
| 19 void DebugInfo::AddCode(uword pc, intptr_t size) { | 511 void DebugInfo::AddCode(uword pc, intptr_t size) { |
| 20 // Nothing to do as there is no support for this on Android. | 512 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); |
| 513 elf_gen->AddCode(pc, size); | |
| 21 } | 514 } |
| 22 | 515 |
| 23 | 516 |
| 24 void DebugInfo::AddCodeRegion(const char* name, uword pc, intptr_t size) { | 517 void DebugInfo::AddCodeRegion(const char* name, uword pc, intptr_t size) { |
| 25 // Nothing to do as there is no support for this on Android. | 518 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); |
| 519 elf_gen->AddCodeRegion(name, pc, size); | |
| 26 } | 520 } |
| 27 | 521 |
| 28 | 522 |
| 29 bool DebugInfo::WriteToMemory(ByteBuffer* region) { | 523 bool DebugInfo::WriteToMemory(ByteBuffer* region) { |
| 30 // Nothing to do as there is no support for this on Android. | 524 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); |
| 31 return false; | 525 return elf_gen->WriteToMemory(region); |
| 32 } | 526 } |
| 33 | 527 |
| 34 | 528 |
| 35 DebugInfo* DebugInfo::NewGenerator() { | 529 DebugInfo* DebugInfo::NewGenerator() { |
| 36 return new DebugInfo(); | 530 return new DebugInfo(); |
| 37 } | 531 } |
| 38 | 532 |
| 39 | 533 |
| 40 void DebugInfo::RegisterSection(const char* name, | 534 void DebugInfo::RegisterSection(const char* name, |
| 41 uword entry_point, | 535 uword entry_point, |
| 42 intptr_t size) { | 536 intptr_t size) { |
| 43 // Nothing to do as there is no support for this on Android. | 537 ElfGen* elf_section = new ElfGen(); |
| 538 ASSERT(elf_section != NULL); | |
| 539 elf_section->AddCode(entry_point, size); | |
| 540 elf_section->AddCodeRegion(name, entry_point, size); | |
| 541 | |
| 542 ByteBuffer* dynamic_region = new ByteBuffer(); | |
| 543 ASSERT(dynamic_region != NULL); | |
| 544 | |
| 545 elf_section->WriteToMemory(dynamic_region); | |
| 546 | |
| 547 ::addDynamicSection(reinterpret_cast<const char*>(dynamic_region->data()), | |
| 548 dynamic_region->size()); | |
| 549 dynamic_region->set_data(NULL); | |
| 550 delete dynamic_region; | |
| 551 delete elf_section; | |
| 44 } | 552 } |
| 45 | 553 |
| 46 | 554 |
| 47 void DebugInfo::UnregisterAllSections() { | 555 void DebugInfo::UnregisterAllSections() { |
| 48 // Nothing to do as there is no support for this on Android. | 556 ::deleteDynamicSections(); |
| 49 } | 557 } |
| 50 | 558 |
| 51 } // namespace dart | 559 } // namespace dart |
| OLD | NEW |