OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 "vm/gdbjit_linux.h" | 7 #include "vm/gdbjit_linux.h" |
8 #include "vm/os.h" | 8 #include "vm/os.h" |
9 #include "vm/utils.h" | 9 #include "vm/utils.h" |
10 #include "vm/thread.h" | 10 #include "vm/thread.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 | 45 |
46 // Add symbol information for a region (includes the start and end symbol), | 46 // Add symbol information for a region (includes the start and end symbol), |
47 // does not add the actual code. | 47 // does not add the actual code. |
48 void AddCodeRegion(const char* name, uword pc, intptr_t size); | 48 void AddCodeRegion(const char* name, uword pc, intptr_t size); |
49 | 49 |
50 // Add specified symbol information, does not add the actual code. | 50 // Add specified symbol information, does not add the actual code. |
51 int AddFunction(const char* name, uword pc, intptr_t size); | 51 int AddFunction(const char* name, uword pc, intptr_t size); |
52 | 52 |
53 // Write out all the Elf information using the specified handle. | 53 // Write out all the Elf information using the specified handle. |
54 bool WriteToFile(File* handle); | 54 bool WriteToFile(File* handle); |
55 bool WriteToMemory(ByteArray* region); | 55 bool WriteToMemory(ByteVector* region); |
56 | 56 |
57 // Register this generated section with GDB using the JIT interface. | 57 // Register this generated section with GDB using the JIT interface. |
58 static void RegisterSectionWithGDB(const char* name, | 58 static void RegisterSectionWithGDB(const char* name, |
59 uword entry_point, | 59 uword entry_point, |
60 intptr_t size); | 60 intptr_t size); |
61 | 61 |
62 // Unregister all generated section from GDB. | 62 // Unregister all generated section from GDB. |
63 static void UnregisterAllSectionsWithGDB(); | 63 static void UnregisterAllSectionsWithGDB(); |
64 | 64 |
65 private: | 65 private: |
66 // ELF helpers | 66 // ELF helpers |
67 typedef int (*OutputWriter)(void* handle, const ByteArray& section); | 67 typedef int (*OutputWriter)(void* handle, const ByteVector& section); |
68 typedef void (*OutputPadder)(void* handle, int padding_size); | 68 typedef void (*OutputPadder)(void* handle, int padding_size); |
69 | 69 |
70 int AddString(ByteArray* buf, const char* str); | 70 int AddString(ByteVector* buf, const char* str); |
71 int AddSectionName(const char* str); | 71 int AddSectionName(const char* str); |
72 int AddName(const char* str); | 72 int AddName(const char* str); |
73 void AddELFHeader(int shoff); | 73 void AddELFHeader(int shoff); |
74 void AddSectionHeader(int section, int offset); | 74 void AddSectionHeader(int section, int offset); |
75 int PadSection(ByteArray* section, int offset, int alignment); | 75 int PadSection(ByteVector* section, int offset, int alignment); |
76 bool WriteOutput(void* handle, OutputWriter writer, OutputPadder padder); | 76 bool WriteOutput(void* handle, OutputWriter writer, OutputPadder padder); |
77 | 77 |
78 uword text_vma_; // text section vma | 78 uword text_vma_; // text section vma |
79 intptr_t text_size_; // text section size | 79 intptr_t text_size_; // text section size |
80 int text_padding_; // padding preceding text section | 80 int text_padding_; // padding preceding text section |
81 | 81 |
82 static const int kNumSections = 5; // we generate 5 sections | 82 static const int kNumSections = 5; // we generate 5 sections |
83 int section_name_[kNumSections]; // array of section name indices | 83 int section_name_[kNumSections]; // array of section name indices |
84 ByteArray section_buf_[kNumSections]; // array of section buffers | 84 ByteVector section_buf_[kNumSections]; // array of section buffers |
85 ByteArray header_; // ELF header buffer | 85 ByteVector header_; // ELF header buffer |
86 ByteArray sheaders_; // section header table buffer | 86 ByteVector sheaders_; // section header table buffer |
87 ByteArray lineprog_; // line statement program, part of '.debug_line' section | 87 ByteVector lineprog_; // line statement program, part of .debug_line section |
88 | 88 |
89 // current state of the DWARF line info generator | 89 // current state of the DWARF line info generator |
90 uintptr_t cur_addr_; // current pc | 90 uintptr_t cur_addr_; // current pc |
91 int map_offset_; | 91 int map_offset_; |
92 uword map_begin_; | 92 uword map_begin_; |
93 uword map_end_; | 93 uword map_end_; |
94 | 94 |
95 Mutex lock_; | 95 Mutex lock_; |
96 }; | 96 }; |
97 | 97 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 172 |
173 | 173 |
174 // Convenience function aligning an integer. | 174 // Convenience function aligning an integer. |
175 static inline uintptr_t Align(uintptr_t x, intptr_t size) { | 175 static inline uintptr_t Align(uintptr_t x, intptr_t size) { |
176 // size is a power of 2 | 176 // size is a power of 2 |
177 ASSERT((size & (size-1)) == 0); | 177 ASSERT((size & (size-1)) == 0); |
178 return (x + (size-1)) & ~(size-1); | 178 return (x + (size-1)) & ~(size-1); |
179 } | 179 } |
180 | 180 |
181 | 181 |
182 // Convenience function writing a single byte to a ByteArray. | 182 // Convenience function writing a single byte to a ByteVector. |
183 static inline void WriteByte(ByteArray* buf, uint8_t byte) { | 183 static inline void WriteByte(ByteVector* buf, uint8_t byte) { |
184 buf->Add(byte); | 184 buf->Add(byte); |
185 } | 185 } |
186 | 186 |
187 | 187 |
188 // Convenience function writing an unsigned native word to a ByteArray. | 188 // Convenience function writing an unsigned native word to a ByteVector. |
189 // The word is 32-bit wide in 32-bit mode and 64-bit wide in 64-bit mode. | 189 // The word is 32-bit wide in 32-bit mode and 64-bit wide in 64-bit mode. |
190 static inline void WriteWord(ByteArray* buf, uword word) { | 190 static inline void WriteWord(ByteVector* buf, uword word) { |
191 uint8_t* p = reinterpret_cast<uint8_t*>(&word); | 191 uint8_t* p = reinterpret_cast<uint8_t*>(&word); |
192 for (size_t i = 0; i < sizeof(word); i++) { | 192 for (size_t i = 0; i < sizeof(word); i++) { |
193 buf->Add(p[i]); | 193 buf->Add(p[i]); |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
197 static inline void WriteInt(ByteArray* buf, int word) { | 197 static inline void WriteInt(ByteVector* buf, int word) { |
198 uint8_t* p = reinterpret_cast<uint8_t*>(&word); | 198 uint8_t* p = reinterpret_cast<uint8_t*>(&word); |
199 for (size_t i = 0; i < sizeof(word); i++) { | 199 for (size_t i = 0; i < sizeof(word); i++) { |
200 buf->Add(p[i]); | 200 buf->Add(p[i]); |
201 } | 201 } |
202 } | 202 } |
203 | 203 |
204 static inline void WriteShort(ByteArray* buf, uint16_t word) { | 204 static inline void WriteShort(ByteVector* buf, uint16_t word) { |
205 uint8_t* p = reinterpret_cast<uint8_t*>(&word); | 205 uint8_t* p = reinterpret_cast<uint8_t*>(&word); |
206 for (size_t i = 0; i < sizeof(word); i++) { | 206 for (size_t i = 0; i < sizeof(word); i++) { |
207 buf->Add(p[i]); | 207 buf->Add(p[i]); |
208 } | 208 } |
209 } | 209 } |
210 | 210 |
211 static inline void WriteString(ByteArray* buf, const char* str) { | 211 static inline void WriteString(ByteVector* buf, const char* str) { |
212 for (size_t i = 0; i < strlen(str); i++) { | 212 for (size_t i = 0; i < strlen(str); i++) { |
213 buf->Add(static_cast<uint8_t>(str[i])); | 213 buf->Add(static_cast<uint8_t>(str[i])); |
214 } | 214 } |
215 } | 215 } |
216 | 216 |
217 static inline void Write(ByteArray* buf, const void* mem, int length) { | 217 static inline void Write(ByteVector* buf, const void* mem, int length) { |
218 const uint8_t* p = reinterpret_cast<const uint8_t*>(mem); | 218 const uint8_t* p = reinterpret_cast<const uint8_t*>(mem); |
219 for (int i = 0; i < length; i++) { | 219 for (int i = 0; i < length; i++) { |
220 buf->Add(p[i]); | 220 buf->Add(p[i]); |
221 } | 221 } |
222 } | 222 } |
223 | 223 |
224 | 224 |
225 // Write given section to file and return written size. | 225 // Write given section to file and return written size. |
226 static int WriteSectionToFile(void* handle, const ByteArray& section) { | 226 static int WriteSectionToFile(void* handle, const ByteVector& section) { |
227 #if 0 | 227 #if 0 |
228 File* fp = reinterpret_cast<File*>(handle); | 228 File* fp = reinterpret_cast<File*>(handle); |
229 int size = section.size(); | 229 int size = section.size(); |
230 fp->WriteFully(section.data(), size); | 230 fp->WriteFully(section.data(), size); |
231 return size; | 231 return size; |
232 #else | 232 #else |
233 return 0; | 233 return 0; |
234 #endif | 234 #endif |
235 } | 235 } |
236 | 236 |
237 | 237 |
238 // Pad output file to specified padding size. | 238 // Pad output file to specified padding size. |
239 static void PadFile(void* handle, int padding_size) { | 239 static void PadFile(void* handle, int padding_size) { |
240 #if 0 | 240 #if 0 |
241 File* fp = reinterpret_cast<File*>(handle); | 241 File* fp = reinterpret_cast<File*>(handle); |
242 for (int i = 0; i < padding_size; i++) { | 242 for (int i = 0; i < padding_size; i++) { |
243 fp->WriteFully("", 1); | 243 fp->WriteFully("", 1); |
244 } | 244 } |
245 #endif | 245 #endif |
246 } | 246 } |
247 | 247 |
248 | 248 |
249 // Write given section to specified memory region and return written size. | 249 // Write given section to specified memory region and return written size. |
250 static int WriteSectionToMemory(void* handle, const ByteArray& section) { | 250 static int WriteSectionToMemory(void* handle, const ByteVector& section) { |
251 ByteArray* buffer = reinterpret_cast<ByteArray*>(handle); | 251 ByteVector* buffer = reinterpret_cast<ByteVector*>(handle); |
252 int size = section.size(); | 252 int size = section.size(); |
253 for (int i = 0; i < size; i++) { | 253 for (int i = 0; i < size; i++) { |
254 buffer->Add(static_cast<uint8_t>(section.data()[i])); | 254 buffer->Add(static_cast<uint8_t>(section.data()[i])); |
255 } | 255 } |
256 return size; | 256 return size; |
257 } | 257 } |
258 | 258 |
259 | 259 |
260 // Pad memory to specified padding size. | 260 // Pad memory to specified padding size. |
261 static void PadMemory(void* handle, int padding_size) { | 261 static void PadMemory(void* handle, int padding_size) { |
262 ByteArray* buffer = reinterpret_cast<ByteArray*>(handle); | 262 ByteVector* buffer = reinterpret_cast<ByteVector*>(handle); |
263 for (int i = 0; i < padding_size; i++) { | 263 for (int i = 0; i < padding_size; i++) { |
264 buffer->Add(static_cast<uint8_t>(0)); | 264 buffer->Add(static_cast<uint8_t>(0)); |
265 } | 265 } |
266 } | 266 } |
267 | 267 |
268 | 268 |
269 // Constructor | 269 // Constructor |
270 ElfGen::ElfGen() | 270 ElfGen::ElfGen() |
271 : text_vma_(0), text_size_(0), text_padding_(0), map_offset_(0), lock_() { | 271 : text_vma_(0), text_size_(0), text_padding_(0), map_offset_(0), lock_() { |
272 for (int i = 0; i < kNumSections; i++) { | 272 for (int i = 0; i < kNumSections; i++) { |
273 ASSERT(section_attr[i].shndx == i); // Verify layout of sections. | 273 ASSERT(section_attr[i].shndx == i); // Verify layout of sections. |
274 section_name_[i] = AddSectionName(section_attr[i].name); | 274 section_name_[i] = AddSectionName(section_attr[i].name); |
275 } | 275 } |
276 // Section header string table always starts with an empty string, which is | 276 // Section header string table always starts with an empty string, which is |
277 // the name of the kUndef section. | 277 // the name of the kUndef section. |
278 ASSERT((section_attr[0].name[0] == '\0') && (section_name_[0] == 0)); | 278 ASSERT((section_attr[0].name[0] == '\0') && (section_name_[0] == 0)); |
279 | 279 |
280 // String table always starts with an empty string. | 280 // String table always starts with an empty string. |
281 AddName(""); | 281 AddName(""); |
282 ASSERT(section_buf_[kStrtab].size() == 1); | 282 ASSERT(section_buf_[kStrtab].size() == 1); |
283 | 283 |
284 // Symbol at index 0 in symtab is always STN_UNDEF (all zero): | 284 // Symbol at index 0 in symtab is always STN_UNDEF (all zero): |
285 ByteArray* symtab = §ion_buf_[kSymtab]; | 285 ByteVector* symtab = §ion_buf_[kSymtab]; |
286 while (symtab->size() < kSymbolSize) { | 286 while (symtab->size() < kSymbolSize) { |
287 WriteInt(symtab, 0); | 287 WriteInt(symtab, 0); |
288 } | 288 } |
289 ASSERT(symtab->size() == kSymbolSize); | 289 ASSERT(symtab->size() == kSymbolSize); |
290 } | 290 } |
291 | 291 |
292 | 292 |
293 // Destructor | 293 // Destructor |
294 ElfGen::~ElfGen() { | 294 ElfGen::~ElfGen() { |
295 } | 295 } |
(...skipping 24 matching lines...) Expand all Loading... |
320 MutexLocker ml(&lock_); | 320 MutexLocker ml(&lock_); |
321 AddFunction(name, pc, size); | 321 AddFunction(name, pc, size); |
322 char end_name[256]; | 322 char end_name[256]; |
323 OS::SNPrint(end_name, sizeof(end_name), "%s_end", name); | 323 OS::SNPrint(end_name, sizeof(end_name), "%s_end", name); |
324 AddFunction(end_name, pc + size, 0); | 324 AddFunction(end_name, pc + size, 0); |
325 } | 325 } |
326 | 326 |
327 | 327 |
328 int ElfGen::AddFunction(const char* name, uword pc, intptr_t size) { | 328 int ElfGen::AddFunction(const char* name, uword pc, intptr_t size) { |
329 ASSERT(text_vma_ != 0); // code must have been added | 329 ASSERT(text_vma_ != 0); // code must have been added |
330 ByteArray* symtab = §ion_buf_[kSymtab]; | 330 ByteVector* symtab = §ion_buf_[kSymtab]; |
331 const int beg = symtab->size(); | 331 const int beg = symtab->size(); |
332 WriteInt(symtab, AddName(name)); // st_name | 332 WriteInt(symtab, AddName(name)); // st_name |
333 #if defined(TARGET_ARCH_X64) | 333 #if defined(TARGET_ARCH_X64) |
334 WriteShort(symtab, (kSTB_LOCAL << 4) + kSTT_FUNC); // st_info + (st_other<<8) | 334 WriteShort(symtab, (kSTB_LOCAL << 4) + kSTT_FUNC); // st_info + (st_other<<8) |
335 WriteShort(symtab, kText); // st_shndx | 335 WriteShort(symtab, kText); // st_shndx |
336 #endif | 336 #endif |
337 WriteWord(symtab, pc); // st_value | 337 WriteWord(symtab, pc); // st_value |
338 WriteWord(symtab, size); // st_size | 338 WriteWord(symtab, size); // st_size |
339 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | 339 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) |
340 // st_info + (st_other<<8) | 340 // st_info + (st_other<<8) |
341 WriteShort(symtab, (kSTB_EXPORTED << 4) + kSTT_FUNC); | 341 WriteShort(symtab, (kSTB_EXPORTED << 4) + kSTT_FUNC); |
342 WriteShort(symtab, kText); // st_shndx | 342 WriteShort(symtab, kText); // st_shndx |
343 #endif | 343 #endif |
344 ASSERT(symtab->size() - beg == kSymbolSize); | 344 ASSERT(symtab->size() - beg == kSymbolSize); |
345 return beg / kSymbolSize; // symbol index in symtab | 345 return beg / kSymbolSize; // symbol index in symtab |
346 } | 346 } |
347 | 347 |
348 | 348 |
349 bool ElfGen::WriteToFile(File* handle) { | 349 bool ElfGen::WriteToFile(File* handle) { |
350 return WriteOutput(handle, WriteSectionToFile, PadFile); | 350 return WriteOutput(handle, WriteSectionToFile, PadFile); |
351 } | 351 } |
352 | 352 |
353 | 353 |
354 bool ElfGen::WriteToMemory(ByteArray* region) { | 354 bool ElfGen::WriteToMemory(ByteVector* region) { |
355 return WriteOutput(region, WriteSectionToMemory, PadMemory); | 355 return WriteOutput(region, WriteSectionToMemory, PadMemory); |
356 } | 356 } |
357 | 357 |
358 | 358 |
359 int ElfGen::AddString(ByteArray* buf, const char* str) { | 359 int ElfGen::AddString(ByteVector* buf, const char* str) { |
360 const int str_index = buf->size(); | 360 const int str_index = buf->size(); |
361 WriteString(buf, str); | 361 WriteString(buf, str); |
362 WriteByte(buf, 0); // terminating '\0' | 362 WriteByte(buf, 0); // terminating '\0' |
363 return str_index; | 363 return str_index; |
364 } | 364 } |
365 | 365 |
366 | 366 |
367 int ElfGen::AddSectionName(const char* str) { | 367 int ElfGen::AddSectionName(const char* str) { |
368 return AddString(§ion_buf_[kShStrtab], str); | 368 return AddString(§ion_buf_[kShStrtab], str); |
369 } | 369 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 WriteInt(&sheaders_, 0); | 423 WriteInt(&sheaders_, 0); |
424 WriteWord(&sheaders_, section_attr[section].sh_addralign); | 424 WriteWord(&sheaders_, section_attr[section].sh_addralign); |
425 WriteWord(&sheaders_, section_attr[section].sh_entsize); | 425 WriteWord(&sheaders_, section_attr[section].sh_entsize); |
426 ASSERT(sheaders_.size() == kSectionHeaderEntrySize * (section + 1)); | 426 ASSERT(sheaders_.size() == kSectionHeaderEntrySize * (section + 1)); |
427 } | 427 } |
428 | 428 |
429 | 429 |
430 // Pads the given section with zero bytes for the given aligment, assuming the | 430 // Pads the given section with zero bytes for the given aligment, assuming the |
431 // section starts at given file offset; returns file offset after padded | 431 // section starts at given file offset; returns file offset after padded |
432 // section. | 432 // section. |
433 int ElfGen::PadSection(ByteArray* section, int offset, int alignment) { | 433 int ElfGen::PadSection(ByteVector* section, int offset, int alignment) { |
434 offset += section->size(); | 434 offset += section->size(); |
435 int aligned_offset = Align(offset, alignment); | 435 int aligned_offset = Align(offset, alignment); |
436 while (offset++ < aligned_offset) { | 436 while (offset++ < aligned_offset) { |
437 WriteByte(section, 0); // one byte padding. | 437 WriteByte(section, 0); // one byte padding. |
438 } | 438 } |
439 return aligned_offset; | 439 return aligned_offset; |
440 } | 440 } |
441 | 441 |
442 | 442 |
443 bool ElfGen::WriteOutput(void* handle, | 443 bool ElfGen::WriteOutput(void* handle, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 elf_gen->AddCode(pc, size); | 503 elf_gen->AddCode(pc, size); |
504 } | 504 } |
505 | 505 |
506 | 506 |
507 void DebugInfo::AddCodeRegion(const char* name, uword pc, intptr_t size) { | 507 void DebugInfo::AddCodeRegion(const char* name, uword pc, intptr_t size) { |
508 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); | 508 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); |
509 elf_gen->AddCodeRegion(name, pc, size); | 509 elf_gen->AddCodeRegion(name, pc, size); |
510 } | 510 } |
511 | 511 |
512 | 512 |
513 bool DebugInfo::WriteToMemory(ByteArray* region) { | 513 bool DebugInfo::WriteToMemory(ByteVector* region) { |
514 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); | 514 ElfGen* elf_gen = reinterpret_cast<ElfGen*>(handle_); |
515 return elf_gen->WriteToMemory(region); | 515 return elf_gen->WriteToMemory(region); |
516 } | 516 } |
517 | 517 |
518 | 518 |
519 DebugInfo* DebugInfo::NewGenerator() { | 519 DebugInfo* DebugInfo::NewGenerator() { |
520 return new DebugInfo(); | 520 return new DebugInfo(); |
521 } | 521 } |
522 | 522 |
523 | 523 |
524 void DebugInfo::RegisterSection(const char* name, | 524 void DebugInfo::RegisterSection(const char* name, |
525 uword entry_point, | 525 uword entry_point, |
526 intptr_t size) { | 526 intptr_t size) { |
527 ElfGen* elf_section = new ElfGen(); | 527 ElfGen* elf_section = new ElfGen(); |
528 ASSERT(elf_section != NULL); | 528 ASSERT(elf_section != NULL); |
529 elf_section->AddCode(entry_point, size); | 529 elf_section->AddCode(entry_point, size); |
530 elf_section->AddCodeRegion(name, entry_point, size); | 530 elf_section->AddCodeRegion(name, entry_point, size); |
531 | 531 |
532 ByteArray* dynamic_region = new ByteArray(); | 532 ByteVector* dynamic_region = new ByteVector(); |
533 ASSERT(dynamic_region != NULL); | 533 ASSERT(dynamic_region != NULL); |
534 | 534 |
535 elf_section->WriteToMemory(dynamic_region); | 535 elf_section->WriteToMemory(dynamic_region); |
536 | 536 |
537 ::addDynamicSection(reinterpret_cast<const char*>(dynamic_region->data()), | 537 ::addDynamicSection(reinterpret_cast<const char*>(dynamic_region->data()), |
538 dynamic_region->size()); | 538 dynamic_region->size()); |
539 dynamic_region->set_data(NULL); | 539 dynamic_region->set_data(NULL); |
540 delete dynamic_region; | 540 delete dynamic_region; |
541 delete elf_section; | 541 delete elf_section; |
542 } | 542 } |
543 | 543 |
544 | 544 |
545 void DebugInfo::UnregisterAllSections() { | 545 void DebugInfo::UnregisterAllSections() { |
546 ::deleteDynamicSections(); | 546 ::deleteDynamicSections(); |
547 } | 547 } |
548 | 548 |
549 } // namespace dart | 549 } // namespace dart |
OLD | NEW |