1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "elf_writer_quick.h" 18 19 #include "base/logging.h" 20 #include "base/stl_util.h" 21 #include "base/unix_file/fd_file.h" 22 #include "buffered_output_stream.h" 23 #include "driver/compiler_driver.h" 24 #include "dwarf.h" 25 #include "elf_utils.h" 26 #include "file_output_stream.h" 27 #include "globals.h" 28 #include "oat.h" 29 #include "oat_writer.h" 30 #include "utils.h" 31 32 namespace art { 33 34 static constexpr Elf32_Word NextOffset(const Elf32_Shdr& cur, const Elf32_Shdr& prev) { 35 return RoundUp(prev.sh_size + prev.sh_offset, cur.sh_addralign); 36 } 37 38 static uint8_t MakeStInfo(uint8_t binding, uint8_t type) { 39 return ((binding) << 4) + ((type) & 0xf); 40 } 41 42 class ElfFilePiece { 43 public: 44 virtual ~ElfFilePiece() {} 45 46 virtual bool Write(File* elf_file) { 47 if (static_cast<off_t>(offset_) != lseek(elf_file->Fd(), offset_, SEEK_SET)) { 48 PLOG(ERROR) << "Failed to seek to " << GetDescription() << " offset " << offset_ << " for " 49 << elf_file->GetPath(); 50 return false; 51 } 52 53 return DoActualWrite(elf_file); 54 } 55 56 static bool Compare(ElfFilePiece* a, ElfFilePiece* b) { 57 return a->offset_ < b->offset_; 58 } 59 60 protected: 61 explicit ElfFilePiece(Elf32_Word offset) : offset_(offset) {} 62 63 virtual std::string GetDescription() = 0; 64 virtual bool DoActualWrite(File* elf_file) = 0; 65 66 Elf32_Word offset_; 67 }; 68 69 class ElfFileMemoryPiece : public ElfFilePiece { 70 public: 71 ElfFileMemoryPiece(const std::string& name, Elf32_Word offset, const void* data, Elf32_Word size) 72 : ElfFilePiece(offset), dbg_name_(name), data_(data), size_(size) {} 73 74 bool DoActualWrite(File* elf_file) OVERRIDE { 75 DCHECK(data_ != nullptr || size_ == 0U) << dbg_name_ << " " << size_; 76 77 if (!elf_file->WriteFully(data_, size_)) { 78 PLOG(ERROR) << "Failed to write " << dbg_name_ << " for " << elf_file->GetPath(); 79 return false; 80 } 81 82 return true; 83 } 84 85 std::string GetDescription() OVERRIDE { 86 return dbg_name_; 87 } 88 89 private: 90 const std::string& dbg_name_; 91 const void *data_; 92 Elf32_Word size_; 93 }; 94 95 class ElfFileRodataPiece : public ElfFilePiece { 96 public: 97 ElfFileRodataPiece(Elf32_Word offset, OatWriter* oat_writer) : ElfFilePiece(offset), 98 oat_writer_(oat_writer) {} 99 100 bool DoActualWrite(File* elf_file) OVERRIDE { 101 std::unique_ptr<BufferedOutputStream> output_stream( 102 new BufferedOutputStream(new FileOutputStream(elf_file))); 103 if (!oat_writer_->Write(output_stream.get())) { 104 PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file->GetPath(); 105 return false; 106 } 107 108 return true; 109 } 110 111 std::string GetDescription() OVERRIDE { 112 return ".rodata"; 113 } 114 115 private: 116 OatWriter* oat_writer_; 117 }; 118 119 class ElfFileOatTextPiece : public ElfFilePiece { 120 public: 121 ElfFileOatTextPiece(Elf32_Word offset, OatWriter* oat_writer) : ElfFilePiece(offset), 122 oat_writer_(oat_writer) {} 123 124 bool DoActualWrite(File* elf_file) OVERRIDE { 125 // All data is written by the ElfFileRodataPiece right now, as the oat writer writes in one 126 // piece. This is for future flexibility. 127 UNUSED(oat_writer_); 128 return true; 129 } 130 131 std::string GetDescription() OVERRIDE { 132 return ".text"; 133 } 134 135 private: 136 OatWriter* oat_writer_; 137 }; 138 139 static bool WriteOutFile(const std::vector<ElfFilePiece*>& pieces, File* elf_file) { 140 // TODO It would be nice if this checked for overlap. 141 for (auto it = pieces.begin(); it != pieces.end(); ++it) { 142 if (!(*it)->Write(elf_file)) { 143 return false; 144 } 145 } 146 return true; 147 } 148 149 bool ElfWriterQuick::ElfBuilder::Write() { 150 // The basic layout of the elf file. Order may be different in final output. 151 // +-------------------------+ 152 // | Elf32_Ehdr | 153 // +-------------------------+ 154 // | Elf32_Phdr PHDR | 155 // | Elf32_Phdr LOAD R | .dynsym .dynstr .hash .rodata 156 // | Elf32_Phdr LOAD R X | .text 157 // | Elf32_Phdr LOAD RW | .dynamic 158 // | Elf32_Phdr DYNAMIC | .dynamic 159 // +-------------------------+ 160 // | .dynsym | 161 // | Elf32_Sym STN_UNDEF | 162 // | Elf32_Sym oatdata | 163 // | Elf32_Sym oatexec | 164 // | Elf32_Sym oatlastword | 165 // +-------------------------+ 166 // | .dynstr | 167 // | \0 | 168 // | oatdata\0 | 169 // | oatexec\0 | 170 // | oatlastword\0 | 171 // | boot.oat\0 | 172 // +-------------------------+ 173 // | .hash | 174 // | Elf32_Word nbucket = b | 175 // | Elf32_Word nchain = c | 176 // | Elf32_Word bucket[0] | 177 // | ... | 178 // | Elf32_Word bucket[b - 1]| 179 // | Elf32_Word chain[0] | 180 // | ... | 181 // | Elf32_Word chain[c - 1] | 182 // +-------------------------+ 183 // | .rodata | 184 // | oatdata..oatexec-4 | 185 // +-------------------------+ 186 // | .text | 187 // | oatexec..oatlastword | 188 // +-------------------------+ 189 // | .dynamic | 190 // | Elf32_Dyn DT_SONAME | 191 // | Elf32_Dyn DT_HASH | 192 // | Elf32_Dyn DT_SYMTAB | 193 // | Elf32_Dyn DT_SYMENT | 194 // | Elf32_Dyn DT_STRTAB | 195 // | Elf32_Dyn DT_STRSZ | 196 // | Elf32_Dyn DT_NULL | 197 // +-------------------------+ (Optional) 198 // | .strtab | (Optional) 199 // | program symbol names | (Optional) 200 // +-------------------------+ (Optional) 201 // | .symtab | (Optional) 202 // | program symbols | (Optional) 203 // +-------------------------+ 204 // | .shstrtab | 205 // | \0 | 206 // | .dynamic\0 | 207 // | .dynsym\0 | 208 // | .dynstr\0 | 209 // | .hash\0 | 210 // | .rodata\0 | 211 // | .text\0 | 212 // | .shstrtab\0 | 213 // | .symtab\0 | (Optional) 214 // | .strtab\0 | (Optional) 215 // | .debug_str\0 | (Optional) 216 // | .debug_info\0 | (Optional) 217 // | .eh_frame\0 | (Optional) 218 // | .debug_abbrev\0 | (Optional) 219 // +-------------------------+ (Optional) 220 // | .debug_str | (Optional) 221 // +-------------------------+ (Optional) 222 // | .debug_info | (Optional) 223 // +-------------------------+ (Optional) 224 // | .eh_frame | (Optional) 225 // +-------------------------+ (Optional) 226 // | .debug_abbrev | (Optional) 227 // +-------------------------+ 228 // | Elf32_Shdr NULL | 229 // | Elf32_Shdr .dynsym | 230 // | Elf32_Shdr .dynstr | 231 // | Elf32_Shdr .hash | 232 // | Elf32_Shdr .text | 233 // | Elf32_Shdr .rodata | 234 // | Elf32_Shdr .dynamic | 235 // | Elf32_Shdr .shstrtab | 236 // | Elf32_Shdr .debug_str | (Optional) 237 // | Elf32_Shdr .debug_info | (Optional) 238 // | Elf32_Shdr .eh_frame | (Optional) 239 // | Elf32_Shdr .debug_abbrev| (Optional) 240 // +-------------------------+ 241 242 243 if (fatal_error_) { 244 return false; 245 } 246 // Step 1. Figure out all the offsets. 247 248 // What phdr is. 249 uint32_t phdr_offset = sizeof(Elf32_Ehdr); 250 const uint8_t PH_PHDR = 0; 251 const uint8_t PH_LOAD_R__ = 1; 252 const uint8_t PH_LOAD_R_X = 2; 253 const uint8_t PH_LOAD_RW_ = 3; 254 const uint8_t PH_DYNAMIC = 4; 255 const uint8_t PH_NUM = 5; 256 uint32_t phdr_size = sizeof(Elf32_Phdr) * PH_NUM; 257 if (debug_logging_) { 258 LOG(INFO) << "phdr_offset=" << phdr_offset << std::hex << " " << phdr_offset; 259 LOG(INFO) << "phdr_size=" << phdr_size << std::hex << " " << phdr_size; 260 } 261 Elf32_Phdr program_headers[PH_NUM]; 262 memset(&program_headers, 0, sizeof(program_headers)); 263 program_headers[PH_PHDR].p_type = PT_PHDR; 264 program_headers[PH_PHDR].p_offset = phdr_offset; 265 program_headers[PH_PHDR].p_vaddr = phdr_offset; 266 program_headers[PH_PHDR].p_paddr = phdr_offset; 267 program_headers[PH_PHDR].p_filesz = sizeof(program_headers); 268 program_headers[PH_PHDR].p_memsz = sizeof(program_headers); 269 program_headers[PH_PHDR].p_flags = PF_R; 270 program_headers[PH_PHDR].p_align = sizeof(Elf32_Word); 271 272 program_headers[PH_LOAD_R__].p_type = PT_LOAD; 273 program_headers[PH_LOAD_R__].p_offset = 0; 274 program_headers[PH_LOAD_R__].p_vaddr = 0; 275 program_headers[PH_LOAD_R__].p_paddr = 0; 276 program_headers[PH_LOAD_R__].p_flags = PF_R; 277 278 program_headers[PH_LOAD_R_X].p_type = PT_LOAD; 279 program_headers[PH_LOAD_R_X].p_flags = PF_R | PF_X; 280 281 program_headers[PH_LOAD_RW_].p_type = PT_LOAD; 282 program_headers[PH_LOAD_RW_].p_flags = PF_R | PF_W; 283 284 program_headers[PH_DYNAMIC].p_type = PT_DYNAMIC; 285 program_headers[PH_DYNAMIC].p_flags = PF_R | PF_W; 286 287 // Get the dynstr string. 288 std::string dynstr(dynsym_builder_.GenerateStrtab()); 289 290 // Add the SONAME to the dynstr. 291 uint32_t dynstr_soname_offset = dynstr.size(); 292 std::string file_name(elf_file_->GetPath()); 293 size_t directory_separator_pos = file_name.rfind('/'); 294 if (directory_separator_pos != std::string::npos) { 295 file_name = file_name.substr(directory_separator_pos + 1); 296 } 297 dynstr += file_name; 298 dynstr += '\0'; 299 if (debug_logging_) { 300 LOG(INFO) << "dynstr size (bytes) =" << dynstr.size() 301 << std::hex << " " << dynstr.size(); 302 LOG(INFO) << "dynsym size (elements)=" << dynsym_builder_.GetSize() 303 << std::hex << " " << dynsym_builder_.GetSize(); 304 } 305 306 // get the strtab 307 std::string strtab; 308 if (IncludingDebugSymbols()) { 309 strtab = symtab_builder_.GenerateStrtab(); 310 if (debug_logging_) { 311 LOG(INFO) << "strtab size (bytes) =" << strtab.size() 312 << std::hex << " " << strtab.size(); 313 LOG(INFO) << "symtab size (elements) =" << symtab_builder_.GetSize() 314 << std::hex << " " << symtab_builder_.GetSize(); 315 } 316 } 317 318 // Get the section header string table. 319 std::vector<Elf32_Shdr*> section_ptrs; 320 std::string shstrtab; 321 shstrtab += '\0'; 322 323 // Setup sym_undef 324 Elf32_Shdr null_hdr; 325 memset(&null_hdr, 0, sizeof(null_hdr)); 326 null_hdr.sh_type = SHT_NULL; 327 null_hdr.sh_link = SHN_UNDEF; 328 section_ptrs.push_back(&null_hdr); 329 330 uint32_t section_index = 1; 331 332 // setup .dynsym 333 section_ptrs.push_back(&dynsym_builder_.section_); 334 AssignSectionStr(&dynsym_builder_, &shstrtab); 335 dynsym_builder_.section_index_ = section_index++; 336 337 // Setup .dynstr 338 section_ptrs.push_back(&dynsym_builder_.strtab_.section_); 339 AssignSectionStr(&dynsym_builder_.strtab_, &shstrtab); 340 dynsym_builder_.strtab_.section_index_ = section_index++; 341 342 // Setup .hash 343 section_ptrs.push_back(&hash_builder_.section_); 344 AssignSectionStr(&hash_builder_, &shstrtab); 345 hash_builder_.section_index_ = section_index++; 346 347 // Setup .rodata 348 section_ptrs.push_back(&rodata_builder_.section_); 349 AssignSectionStr(&rodata_builder_, &shstrtab); 350 rodata_builder_.section_index_ = section_index++; 351 352 // Setup .text 353 section_ptrs.push_back(&text_builder_.section_); 354 AssignSectionStr(&text_builder_, &shstrtab); 355 text_builder_.section_index_ = section_index++; 356 357 // Setup .dynamic 358 section_ptrs.push_back(&dynamic_builder_.section_); 359 AssignSectionStr(&dynamic_builder_, &shstrtab); 360 dynamic_builder_.section_index_ = section_index++; 361 362 if (IncludingDebugSymbols()) { 363 // Setup .symtab 364 section_ptrs.push_back(&symtab_builder_.section_); 365 AssignSectionStr(&symtab_builder_, &shstrtab); 366 symtab_builder_.section_index_ = section_index++; 367 368 // Setup .strtab 369 section_ptrs.push_back(&symtab_builder_.strtab_.section_); 370 AssignSectionStr(&symtab_builder_.strtab_, &shstrtab); 371 symtab_builder_.strtab_.section_index_ = section_index++; 372 } 373 ElfRawSectionBuilder* it = other_builders_.data(); 374 for (uint32_t cnt = 0; cnt < other_builders_.size(); ++it, ++cnt) { 375 // Setup all the other sections. 376 section_ptrs.push_back(&it->section_); 377 AssignSectionStr(it, &shstrtab); 378 it->section_index_ = section_index++; 379 } 380 381 // Setup shstrtab 382 section_ptrs.push_back(&shstrtab_builder_.section_); 383 AssignSectionStr(&shstrtab_builder_, &shstrtab); 384 shstrtab_builder_.section_index_ = section_index++; 385 386 if (debug_logging_) { 387 LOG(INFO) << ".shstrtab size (bytes) =" << shstrtab.size() 388 << std::hex << " " << shstrtab.size(); 389 LOG(INFO) << "section list size (elements)=" << section_ptrs.size() 390 << std::hex << " " << section_ptrs.size(); 391 } 392 393 // Fill in the hash section. 394 std::vector<Elf32_Word> hash = dynsym_builder_.GenerateHashContents(); 395 396 if (debug_logging_) { 397 LOG(INFO) << ".hash size (bytes)=" << hash.size() * sizeof(Elf32_Word) 398 << std::hex << " " << hash.size() * sizeof(Elf32_Word); 399 } 400 401 Elf32_Word base_offset = sizeof(Elf32_Ehdr) + sizeof(program_headers); 402 std::vector<ElfFilePiece*> pieces; 403 404 // Get the layout in the sections. 405 // 406 // Get the layout of the dynsym section. 407 dynsym_builder_.section_.sh_offset = RoundUp(base_offset, dynsym_builder_.section_.sh_addralign); 408 dynsym_builder_.section_.sh_addr = dynsym_builder_.section_.sh_offset; 409 dynsym_builder_.section_.sh_size = dynsym_builder_.GetSize() * sizeof(Elf32_Sym); 410 dynsym_builder_.section_.sh_link = dynsym_builder_.GetLink(); 411 412 // Get the layout of the dynstr section. 413 dynsym_builder_.strtab_.section_.sh_offset = NextOffset(dynsym_builder_.strtab_.section_, 414 dynsym_builder_.section_); 415 dynsym_builder_.strtab_.section_.sh_addr = dynsym_builder_.strtab_.section_.sh_offset; 416 dynsym_builder_.strtab_.section_.sh_size = dynstr.size(); 417 dynsym_builder_.strtab_.section_.sh_link = dynsym_builder_.strtab_.GetLink(); 418 419 // Get the layout of the hash section 420 hash_builder_.section_.sh_offset = NextOffset(hash_builder_.section_, 421 dynsym_builder_.strtab_.section_); 422 hash_builder_.section_.sh_addr = hash_builder_.section_.sh_offset; 423 hash_builder_.section_.sh_size = hash.size() * sizeof(Elf32_Word); 424 hash_builder_.section_.sh_link = hash_builder_.GetLink(); 425 426 // Get the layout of the rodata section. 427 rodata_builder_.section_.sh_offset = NextOffset(rodata_builder_.section_, 428 hash_builder_.section_); 429 rodata_builder_.section_.sh_addr = rodata_builder_.section_.sh_offset; 430 rodata_builder_.section_.sh_size = rodata_builder_.size_; 431 rodata_builder_.section_.sh_link = rodata_builder_.GetLink(); 432 433 // Get the layout of the text section. 434 text_builder_.section_.sh_offset = NextOffset(text_builder_.section_, rodata_builder_.section_); 435 text_builder_.section_.sh_addr = text_builder_.section_.sh_offset; 436 text_builder_.section_.sh_size = text_builder_.size_; 437 text_builder_.section_.sh_link = text_builder_.GetLink(); 438 CHECK_ALIGNED(rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size, kPageSize); 439 440 // Get the layout of the dynamic section. 441 dynamic_builder_.section_.sh_offset = NextOffset(dynamic_builder_.section_, 442 text_builder_.section_); 443 dynamic_builder_.section_.sh_addr = dynamic_builder_.section_.sh_offset; 444 dynamic_builder_.section_.sh_size = dynamic_builder_.GetSize() * sizeof(Elf32_Dyn); 445 dynamic_builder_.section_.sh_link = dynamic_builder_.GetLink(); 446 447 Elf32_Shdr prev = dynamic_builder_.section_; 448 if (IncludingDebugSymbols()) { 449 // Get the layout of the symtab section. 450 symtab_builder_.section_.sh_offset = NextOffset(symtab_builder_.section_, 451 dynamic_builder_.section_); 452 symtab_builder_.section_.sh_addr = 0; 453 // Add to leave space for the null symbol. 454 symtab_builder_.section_.sh_size = symtab_builder_.GetSize() * sizeof(Elf32_Sym); 455 symtab_builder_.section_.sh_link = symtab_builder_.GetLink(); 456 457 // Get the layout of the dynstr section. 458 symtab_builder_.strtab_.section_.sh_offset = NextOffset(symtab_builder_.strtab_.section_, 459 symtab_builder_.section_); 460 symtab_builder_.strtab_.section_.sh_addr = 0; 461 symtab_builder_.strtab_.section_.sh_size = strtab.size(); 462 symtab_builder_.strtab_.section_.sh_link = symtab_builder_.strtab_.GetLink(); 463 464 prev = symtab_builder_.strtab_.section_; 465 } 466 if (debug_logging_) { 467 LOG(INFO) << "dynsym off=" << dynsym_builder_.section_.sh_offset 468 << " dynsym size=" << dynsym_builder_.section_.sh_size; 469 LOG(INFO) << "dynstr off=" << dynsym_builder_.strtab_.section_.sh_offset 470 << " dynstr size=" << dynsym_builder_.strtab_.section_.sh_size; 471 LOG(INFO) << "hash off=" << hash_builder_.section_.sh_offset 472 << " hash size=" << hash_builder_.section_.sh_size; 473 LOG(INFO) << "rodata off=" << rodata_builder_.section_.sh_offset 474 << " rodata size=" << rodata_builder_.section_.sh_size; 475 LOG(INFO) << "text off=" << text_builder_.section_.sh_offset 476 << " text size=" << text_builder_.section_.sh_size; 477 LOG(INFO) << "dynamic off=" << dynamic_builder_.section_.sh_offset 478 << " dynamic size=" << dynamic_builder_.section_.sh_size; 479 if (IncludingDebugSymbols()) { 480 LOG(INFO) << "symtab off=" << symtab_builder_.section_.sh_offset 481 << " symtab size=" << symtab_builder_.section_.sh_size; 482 LOG(INFO) << "strtab off=" << symtab_builder_.strtab_.section_.sh_offset 483 << " strtab size=" << symtab_builder_.strtab_.section_.sh_size; 484 } 485 } 486 // Get the layout of the extra sections. (This will deal with the debug 487 // sections if they are there) 488 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) { 489 it->section_.sh_offset = NextOffset(it->section_, prev); 490 it->section_.sh_addr = 0; 491 it->section_.sh_size = it->GetBuffer()->size(); 492 it->section_.sh_link = it->GetLink(); 493 494 // We postpone adding an ElfFilePiece to keep the order in "pieces." 495 496 prev = it->section_; 497 if (debug_logging_) { 498 LOG(INFO) << it->name_ << " off=" << it->section_.sh_offset 499 << " " << it->name_ << " size=" << it->section_.sh_size; 500 } 501 } 502 // Get the layout of the shstrtab section 503 shstrtab_builder_.section_.sh_offset = NextOffset(shstrtab_builder_.section_, prev); 504 shstrtab_builder_.section_.sh_addr = 0; 505 shstrtab_builder_.section_.sh_size = shstrtab.size(); 506 shstrtab_builder_.section_.sh_link = shstrtab_builder_.GetLink(); 507 if (debug_logging_) { 508 LOG(INFO) << "shstrtab off=" << shstrtab_builder_.section_.sh_offset 509 << " shstrtab size=" << shstrtab_builder_.section_.sh_size; 510 } 511 512 // The section list comes after come after. 513 Elf32_Word sections_offset = RoundUp( 514 shstrtab_builder_.section_.sh_offset + shstrtab_builder_.section_.sh_size, 515 sizeof(Elf32_Word)); 516 517 // Setup the actual symbol arrays. 518 std::vector<Elf32_Sym> dynsym = dynsym_builder_.GenerateSymtab(); 519 CHECK_EQ(dynsym.size() * sizeof(Elf32_Sym), dynsym_builder_.section_.sh_size); 520 std::vector<Elf32_Sym> symtab; 521 if (IncludingDebugSymbols()) { 522 symtab = symtab_builder_.GenerateSymtab(); 523 CHECK_EQ(symtab.size() * sizeof(Elf32_Sym), symtab_builder_.section_.sh_size); 524 } 525 526 // Setup the dynamic section. 527 // This will add the 2 values we cannot know until now time, namely the size 528 // and the soname_offset. 529 std::vector<Elf32_Dyn> dynamic = dynamic_builder_.GetDynamics(dynstr.size(), 530 dynstr_soname_offset); 531 CHECK_EQ(dynamic.size() * sizeof(Elf32_Dyn), dynamic_builder_.section_.sh_size); 532 533 // Finish setup of the program headers now that we know the layout of the 534 // whole file. 535 Elf32_Word load_r_size = rodata_builder_.section_.sh_offset + rodata_builder_.section_.sh_size; 536 program_headers[PH_LOAD_R__].p_filesz = load_r_size; 537 program_headers[PH_LOAD_R__].p_memsz = load_r_size; 538 program_headers[PH_LOAD_R__].p_align = rodata_builder_.section_.sh_addralign; 539 540 Elf32_Word load_rx_size = text_builder_.section_.sh_size; 541 program_headers[PH_LOAD_R_X].p_offset = text_builder_.section_.sh_offset; 542 program_headers[PH_LOAD_R_X].p_vaddr = text_builder_.section_.sh_offset; 543 program_headers[PH_LOAD_R_X].p_paddr = text_builder_.section_.sh_offset; 544 program_headers[PH_LOAD_R_X].p_filesz = load_rx_size; 545 program_headers[PH_LOAD_R_X].p_memsz = load_rx_size; 546 program_headers[PH_LOAD_R_X].p_align = text_builder_.section_.sh_addralign; 547 548 program_headers[PH_LOAD_RW_].p_offset = dynamic_builder_.section_.sh_offset; 549 program_headers[PH_LOAD_RW_].p_vaddr = dynamic_builder_.section_.sh_offset; 550 program_headers[PH_LOAD_RW_].p_paddr = dynamic_builder_.section_.sh_offset; 551 program_headers[PH_LOAD_RW_].p_filesz = dynamic_builder_.section_.sh_size; 552 program_headers[PH_LOAD_RW_].p_memsz = dynamic_builder_.section_.sh_size; 553 program_headers[PH_LOAD_RW_].p_align = dynamic_builder_.section_.sh_addralign; 554 555 program_headers[PH_DYNAMIC].p_offset = dynamic_builder_.section_.sh_offset; 556 program_headers[PH_DYNAMIC].p_vaddr = dynamic_builder_.section_.sh_offset; 557 program_headers[PH_DYNAMIC].p_paddr = dynamic_builder_.section_.sh_offset; 558 program_headers[PH_DYNAMIC].p_filesz = dynamic_builder_.section_.sh_size; 559 program_headers[PH_DYNAMIC].p_memsz = dynamic_builder_.section_.sh_size; 560 program_headers[PH_DYNAMIC].p_align = dynamic_builder_.section_.sh_addralign; 561 562 // Finish setup of the Ehdr values. 563 elf_header_.e_phoff = phdr_offset; 564 elf_header_.e_shoff = sections_offset; 565 elf_header_.e_phnum = PH_NUM; 566 elf_header_.e_shnum = section_ptrs.size(); 567 elf_header_.e_shstrndx = shstrtab_builder_.section_index_; 568 569 // Add the rest of the pieces to the list. 570 pieces.push_back(new ElfFileMemoryPiece("Elf Header", 0, &elf_header_, sizeof(elf_header_))); 571 pieces.push_back(new ElfFileMemoryPiece("Program headers", phdr_offset, 572 &program_headers, sizeof(program_headers))); 573 pieces.push_back(new ElfFileMemoryPiece(".dynamic", dynamic_builder_.section_.sh_offset, 574 dynamic.data(), dynamic_builder_.section_.sh_size)); 575 pieces.push_back(new ElfFileMemoryPiece(".dynsym", dynsym_builder_.section_.sh_offset, 576 dynsym.data(), dynsym.size() * sizeof(Elf32_Sym))); 577 pieces.push_back(new ElfFileMemoryPiece(".dynstr", dynsym_builder_.strtab_.section_.sh_offset, 578 dynstr.c_str(), dynstr.size())); 579 pieces.push_back(new ElfFileMemoryPiece(".hash", hash_builder_.section_.sh_offset, 580 hash.data(), hash.size() * sizeof(Elf32_Word))); 581 pieces.push_back(new ElfFileRodataPiece(rodata_builder_.section_.sh_offset, oat_writer_)); 582 pieces.push_back(new ElfFileOatTextPiece(text_builder_.section_.sh_offset, oat_writer_)); 583 if (IncludingDebugSymbols()) { 584 pieces.push_back(new ElfFileMemoryPiece(".symtab", symtab_builder_.section_.sh_offset, 585 symtab.data(), symtab.size() * sizeof(Elf32_Sym))); 586 pieces.push_back(new ElfFileMemoryPiece(".strtab", symtab_builder_.strtab_.section_.sh_offset, 587 strtab.c_str(), strtab.size())); 588 } 589 pieces.push_back(new ElfFileMemoryPiece(".shstrtab", shstrtab_builder_.section_.sh_offset, 590 &shstrtab[0], shstrtab.size())); 591 for (uint32_t i = 0; i < section_ptrs.size(); ++i) { 592 // Just add all the sections in individually since they are all over the 593 // place on the heap/stack. 594 Elf32_Word cur_off = sections_offset + i * sizeof(Elf32_Shdr); 595 pieces.push_back(new ElfFileMemoryPiece("section table piece", cur_off, 596 section_ptrs[i], sizeof(Elf32_Shdr))); 597 } 598 599 // Postponed debug info. 600 for (auto it = other_builders_.begin(); it != other_builders_.end(); ++it) { 601 pieces.push_back(new ElfFileMemoryPiece(it->name_, it->section_.sh_offset, 602 it->GetBuffer()->data(), it->GetBuffer()->size())); 603 } 604 605 if (!WriteOutFile(pieces, elf_file_)) { 606 LOG(ERROR) << "Unable to write to file " << elf_file_->GetPath(); 607 608 STLDeleteElements(&pieces); // Have to manually clean pieces. 609 return false; 610 } 611 612 STLDeleteElements(&pieces); // Have to manually clean pieces. 613 return true; 614 } 615 616 void ElfWriterQuick::ElfBuilder::SetupDynamic() { 617 dynamic_builder_.AddDynamicTag(DT_HASH, 0, &hash_builder_); 618 dynamic_builder_.AddDynamicTag(DT_STRTAB, 0, &dynsym_builder_.strtab_); 619 dynamic_builder_.AddDynamicTag(DT_SYMTAB, 0, &dynsym_builder_); 620 dynamic_builder_.AddDynamicTag(DT_SYMENT, sizeof(Elf32_Sym)); 621 } 622 623 void ElfWriterQuick::ElfBuilder::SetupRequiredSymbols() { 624 dynsym_builder_.AddSymbol("oatdata", &rodata_builder_, 0, true, 625 rodata_builder_.size_, STB_GLOBAL, STT_OBJECT); 626 dynsym_builder_.AddSymbol("oatexec", &text_builder_, 0, true, 627 text_builder_.size_, STB_GLOBAL, STT_OBJECT); 628 dynsym_builder_.AddSymbol("oatlastword", &text_builder_, text_builder_.size_ - 4, 629 true, 4, STB_GLOBAL, STT_OBJECT); 630 } 631 632 void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un) { 633 if (tag == DT_NULL) { 634 return; 635 } 636 dynamics_.push_back({nullptr, tag, d_un}); 637 } 638 639 void ElfWriterQuick::ElfDynamicBuilder::AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un, 640 ElfSectionBuilder* section) { 641 if (tag == DT_NULL) { 642 return; 643 } 644 dynamics_.push_back({section, tag, d_un}); 645 } 646 647 std::vector<Elf32_Dyn> ElfWriterQuick::ElfDynamicBuilder::GetDynamics(Elf32_Word strsz, 648 Elf32_Word soname) { 649 std::vector<Elf32_Dyn> ret; 650 for (auto it = dynamics_.cbegin(); it != dynamics_.cend(); ++it) { 651 if (it->section_) { 652 // We are adding an address relative to a section. 653 ret.push_back( 654 {it->tag_, {it->off_ + it->section_->section_.sh_addr}}); 655 } else { 656 ret.push_back({it->tag_, {it->off_}}); 657 } 658 } 659 ret.push_back({DT_STRSZ, {strsz}}); 660 ret.push_back({DT_SONAME, {soname}}); 661 ret.push_back({DT_NULL, {0}}); 662 return ret; 663 } 664 665 std::vector<Elf32_Sym> ElfWriterQuick::ElfSymtabBuilder::GenerateSymtab() { 666 std::vector<Elf32_Sym> ret; 667 Elf32_Sym undef_sym; 668 memset(&undef_sym, 0, sizeof(undef_sym)); 669 undef_sym.st_shndx = SHN_UNDEF; 670 ret.push_back(undef_sym); 671 672 for (auto it = symbols_.cbegin(); it != symbols_.cend(); ++it) { 673 Elf32_Sym sym; 674 memset(&sym, 0, sizeof(sym)); 675 sym.st_name = it->name_idx_; 676 if (it->is_relative_) { 677 sym.st_value = it->addr_ + it->section_->section_.sh_offset; 678 } else { 679 sym.st_value = it->addr_; 680 } 681 sym.st_size = it->size_; 682 sym.st_other = it->other_; 683 sym.st_shndx = it->section_->section_index_; 684 sym.st_info = it->info_; 685 686 ret.push_back(sym); 687 } 688 return ret; 689 } 690 691 std::string ElfWriterQuick::ElfSymtabBuilder::GenerateStrtab() { 692 std::string tab; 693 tab += '\0'; 694 for (auto it = symbols_.begin(); it != symbols_.end(); ++it) { 695 it->name_idx_ = tab.size(); 696 tab += it->name_; 697 tab += '\0'; 698 } 699 strtab_.section_.sh_size = tab.size(); 700 return tab; 701 } 702 703 void ElfWriterQuick::ElfBuilder::AssignSectionStr( 704 ElfSectionBuilder* builder, std::string* strtab) { 705 builder->section_.sh_name = strtab->size(); 706 *strtab += builder->name_; 707 *strtab += '\0'; 708 if (debug_logging_) { 709 LOG(INFO) << "adding section name \"" << builder->name_ << "\" " 710 << "to shstrtab at offset " << builder->section_.sh_name; 711 } 712 } 713 714 // from bionic 715 static unsigned elfhash(const char *_name) { 716 const unsigned char *name = (const unsigned char *) _name; 717 unsigned h = 0, g; 718 719 while (*name) { 720 h = (h << 4) + *name++; 721 g = h & 0xf0000000; 722 h ^= g; 723 h ^= g >> 24; 724 } 725 return h; 726 } 727 728 729 std::vector<Elf32_Word> ElfWriterQuick::ElfSymtabBuilder::GenerateHashContents() { 730 // Here is how The ELF hash table works. 731 // There are 3 arrays to worry about. 732 // * The symbol table where the symbol information is. 733 // * The bucket array which is an array of indexes into the symtab and chain. 734 // * The chain array which is also an array of indexes into the symtab and chain. 735 // 736 // Lets say the state is something like this. 737 // +--------+ +--------+ +-----------+ 738 // | symtab | | bucket | | chain | 739 // | nullptr | | 1 | | STN_UNDEF | 740 // | <sym1> | | 4 | | 2 | 741 // | <sym2> | | | | 5 | 742 // | <sym3> | | | | STN_UNDEF | 743 // | <sym4> | | | | 3 | 744 // | <sym5> | | | | STN_UNDEF | 745 // +--------+ +--------+ +-----------+ 746 // 747 // The lookup process (in python psudocode) is 748 // 749 // def GetSym(name): 750 // # NB STN_UNDEF == 0 751 // indx = bucket[elfhash(name) % num_buckets] 752 // while indx != STN_UNDEF: 753 // if GetSymbolName(symtab[indx]) == name: 754 // return symtab[indx] 755 // indx = chain[indx] 756 // return SYMBOL_NOT_FOUND 757 // 758 // Between bucket and chain arrays every symtab index must be present exactly 759 // once (except for STN_UNDEF, which must be present 1 + num_bucket times). 760 761 // Select number of buckets. 762 // This is essentially arbitrary. 763 Elf32_Word nbuckets; 764 Elf32_Word chain_size = GetSize(); 765 if (symbols_.size() < 8) { 766 nbuckets = 2; 767 } else if (symbols_.size() < 32) { 768 nbuckets = 4; 769 } else if (symbols_.size() < 256) { 770 nbuckets = 16; 771 } else { 772 // Have about 32 ids per bucket. 773 nbuckets = RoundUp(symbols_.size()/32, 2); 774 } 775 std::vector<Elf32_Word> hash; 776 hash.push_back(nbuckets); 777 hash.push_back(chain_size); 778 uint32_t bucket_offset = hash.size(); 779 uint32_t chain_offset = bucket_offset + nbuckets; 780 hash.resize(hash.size() + nbuckets + chain_size, 0); 781 782 Elf32_Word* buckets = hash.data() + bucket_offset; 783 Elf32_Word* chain = hash.data() + chain_offset; 784 785 // Set up the actual hash table. 786 for (Elf32_Word i = 0; i < symbols_.size(); i++) { 787 // Add 1 since we need to have the null symbol that is not in the symbols 788 // list. 789 Elf32_Word index = i + 1; 790 Elf32_Word hash_val = static_cast<Elf32_Word>(elfhash(symbols_[i].name_.c_str())) % nbuckets; 791 if (buckets[hash_val] == 0) { 792 buckets[hash_val] = index; 793 } else { 794 hash_val = buckets[hash_val]; 795 CHECK_LT(hash_val, chain_size); 796 while (chain[hash_val] != 0) { 797 hash_val = chain[hash_val]; 798 CHECK_LT(hash_val, chain_size); 799 } 800 chain[hash_val] = index; 801 // Check for loops. Works because if this is non-empty then there must be 802 // another cell which already contains the same symbol index as this one, 803 // which means some symbol has more then one name, which isn't allowed. 804 CHECK_EQ(chain[index], static_cast<Elf32_Word>(0)); 805 } 806 } 807 808 return hash; 809 } 810 811 void ElfWriterQuick::ElfBuilder::SetupEhdr() { 812 memset(&elf_header_, 0, sizeof(elf_header_)); 813 elf_header_.e_ident[EI_MAG0] = ELFMAG0; 814 elf_header_.e_ident[EI_MAG1] = ELFMAG1; 815 elf_header_.e_ident[EI_MAG2] = ELFMAG2; 816 elf_header_.e_ident[EI_MAG3] = ELFMAG3; 817 elf_header_.e_ident[EI_CLASS] = ELFCLASS32; 818 elf_header_.e_ident[EI_DATA] = ELFDATA2LSB; 819 elf_header_.e_ident[EI_VERSION] = EV_CURRENT; 820 elf_header_.e_ident[EI_OSABI] = ELFOSABI_LINUX; 821 elf_header_.e_ident[EI_ABIVERSION] = 0; 822 elf_header_.e_type = ET_DYN; 823 elf_header_.e_version = 1; 824 elf_header_.e_entry = 0; 825 elf_header_.e_ehsize = sizeof(Elf32_Ehdr); 826 elf_header_.e_phentsize = sizeof(Elf32_Phdr); 827 elf_header_.e_shentsize = sizeof(Elf32_Shdr); 828 elf_header_.e_phoff = sizeof(Elf32_Ehdr); 829 } 830 831 void ElfWriterQuick::ElfBuilder::SetISA(InstructionSet isa) { 832 switch (isa) { 833 case kArm: 834 // Fall through. 835 case kThumb2: { 836 elf_header_.e_machine = EM_ARM; 837 elf_header_.e_flags = EF_ARM_EABI_VER5; 838 break; 839 } 840 case kArm64: { 841 elf_header_.e_machine = EM_AARCH64; 842 elf_header_.e_flags = 0; 843 break; 844 } 845 case kX86: { 846 elf_header_.e_machine = EM_386; 847 elf_header_.e_flags = 0; 848 break; 849 } 850 case kX86_64: { 851 elf_header_.e_machine = EM_X86_64; 852 elf_header_.e_flags = 0; 853 break; 854 } 855 case kMips: { 856 elf_header_.e_machine = EM_MIPS; 857 elf_header_.e_flags = (EF_MIPS_NOREORDER | 858 EF_MIPS_PIC | 859 EF_MIPS_CPIC | 860 EF_MIPS_ABI_O32 | 861 EF_MIPS_ARCH_32R2); 862 break; 863 } 864 default: { 865 fatal_error_ = true; 866 LOG(FATAL) << "Unknown instruction set: " << isa; 867 break; 868 } 869 } 870 } 871 872 void ElfWriterQuick::ElfSymtabBuilder::AddSymbol( 873 const std::string& name, const ElfSectionBuilder* section, Elf32_Addr addr, 874 bool is_relative, Elf32_Word size, uint8_t binding, uint8_t type, uint8_t other) { 875 CHECK(section); 876 ElfSymtabBuilder::ElfSymbolState state {name, section, addr, size, is_relative, 877 MakeStInfo(binding, type), other, 0}; 878 symbols_.push_back(state); 879 } 880 881 bool ElfWriterQuick::Create(File* elf_file, 882 OatWriter* oat_writer, 883 const std::vector<const DexFile*>& dex_files, 884 const std::string& android_root, 885 bool is_host, 886 const CompilerDriver& driver) { 887 ElfWriterQuick elf_writer(driver, elf_file); 888 return elf_writer.Write(oat_writer, dex_files, android_root, is_host); 889 } 890 891 // Add patch information to this section. Each patch is a Elf32_Word that 892 // identifies an offset from the start of the text section 893 void ElfWriterQuick::ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug) { 894 const size_t size = 895 compiler_driver_->GetCodeToPatch().size() + 896 compiler_driver_->GetMethodsToPatch().size() + 897 compiler_driver_->GetClassesToPatch().size() + 898 compiler_driver_->GetStringsToPatch().size(); 899 if (size == 0) { 900 if (debug) { 901 LOG(INFO) << "No patches to record"; 902 } 903 return; 904 } 905 buffer->resize(size * sizeof(uintptr_t)); 906 if (debug) { 907 LOG(INFO) << "Patches reserved for " << size; 908 } 909 } 910 911 bool ElfWriterQuick::Write(OatWriter* oat_writer, 912 const std::vector<const DexFile*>& dex_files_unused, 913 const std::string& android_root_unused, 914 bool is_host_unused) { 915 const bool debug = false; 916 const bool add_symbols = oat_writer->DidAddSymbols(); 917 const OatHeader& oat_header = oat_writer->GetOatHeader(); 918 Elf32_Word oat_data_size = oat_header.GetExecutableOffset(); 919 uint32_t oat_exec_size = oat_writer->GetSize() - oat_data_size; 920 921 ElfBuilder builder(oat_writer, elf_file_, compiler_driver_->GetInstructionSet(), 0, 922 oat_data_size, oat_data_size, oat_exec_size, add_symbols, debug); 923 924 if (add_symbols) { 925 AddDebugSymbols(builder, oat_writer, debug); 926 } 927 928 bool generateDebugInformation = compiler_driver_->GetCallFrameInformation() != nullptr; 929 if (generateDebugInformation) { 930 ElfRawSectionBuilder debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 931 ElfRawSectionBuilder debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 932 ElfRawSectionBuilder debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0); 933 ElfRawSectionBuilder eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0); 934 eh_frame.SetBuffer(*compiler_driver_->GetCallFrameInformation()); 935 936 FillInCFIInformation(oat_writer, debug_info.GetBuffer(), 937 debug_abbrev.GetBuffer(), debug_str.GetBuffer()); 938 builder.RegisterRawSection(debug_info); 939 builder.RegisterRawSection(debug_abbrev); 940 builder.RegisterRawSection(eh_frame); 941 builder.RegisterRawSection(debug_str); 942 } 943 944 if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) { 945 ElfRawSectionBuilder oat_patches(".oat_patches", SHT_OAT_PATCH, 0, NULL, 0, 946 sizeof(size_t), sizeof(size_t)); 947 ReservePatchSpace(oat_patches.GetBuffer(), debug); 948 builder.RegisterRawSection(oat_patches); 949 } 950 951 return builder.Write(); 952 } 953 954 void ElfWriterQuick::AddDebugSymbols(ElfBuilder& builder, OatWriter* oat_writer, bool debug) { 955 const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo(); 956 ElfSymtabBuilder* symtab = &builder.symtab_builder_; 957 for (auto it = method_info.begin(); it != method_info.end(); ++it) { 958 symtab->AddSymbol(it->method_name_, &builder.text_builder_, it->low_pc_, true, 959 it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC); 960 } 961 } 962 963 static void UpdateWord(std::vector<uint8_t>*buf, int offset, int data) { 964 (*buf)[offset+0] = data; 965 (*buf)[offset+1] = data >> 8; 966 (*buf)[offset+2] = data >> 16; 967 (*buf)[offset+3] = data >> 24; 968 } 969 970 static void PushWord(std::vector<uint8_t>*buf, int data) { 971 buf->push_back(data & 0xff); 972 buf->push_back((data >> 8) & 0xff); 973 buf->push_back((data >> 16) & 0xff); 974 buf->push_back((data >> 24) & 0xff); 975 } 976 977 static void PushHalf(std::vector<uint8_t>*buf, int data) { 978 buf->push_back(data & 0xff); 979 buf->push_back((data >> 8) & 0xff); 980 } 981 982 void ElfWriterQuick::FillInCFIInformation(OatWriter* oat_writer, 983 std::vector<uint8_t>* dbg_info, 984 std::vector<uint8_t>* dbg_abbrev, 985 std::vector<uint8_t>* dbg_str) { 986 // Create the debug_abbrev section with boilerplate information. 987 // We only care about low_pc and high_pc right now for the compilation 988 // unit and methods. 989 990 // Tag 1: Compilation unit: DW_TAG_compile_unit. 991 dbg_abbrev->push_back(1); 992 dbg_abbrev->push_back(DW_TAG_compile_unit); 993 994 // There are children (the methods). 995 dbg_abbrev->push_back(DW_CHILDREN_yes); 996 997 // DW_LANG_Java DW_FORM_data1. 998 dbg_abbrev->push_back(DW_AT_language); 999 dbg_abbrev->push_back(DW_FORM_data1); 1000 1001 // DW_AT_low_pc DW_FORM_addr. 1002 dbg_abbrev->push_back(DW_AT_low_pc); 1003 dbg_abbrev->push_back(DW_FORM_addr); 1004 1005 // DW_AT_high_pc DW_FORM_addr. 1006 dbg_abbrev->push_back(DW_AT_high_pc); 1007 dbg_abbrev->push_back(DW_FORM_addr); 1008 1009 // End of DW_TAG_compile_unit. 1010 PushHalf(dbg_abbrev, 0); 1011 1012 // Tag 2: Compilation unit: DW_TAG_subprogram. 1013 dbg_abbrev->push_back(2); 1014 dbg_abbrev->push_back(DW_TAG_subprogram); 1015 1016 // There are no children. 1017 dbg_abbrev->push_back(DW_CHILDREN_no); 1018 1019 // Name of the method. 1020 dbg_abbrev->push_back(DW_AT_name); 1021 dbg_abbrev->push_back(DW_FORM_strp); 1022 1023 // DW_AT_low_pc DW_FORM_addr. 1024 dbg_abbrev->push_back(DW_AT_low_pc); 1025 dbg_abbrev->push_back(DW_FORM_addr); 1026 1027 // DW_AT_high_pc DW_FORM_addr. 1028 dbg_abbrev->push_back(DW_AT_high_pc); 1029 dbg_abbrev->push_back(DW_FORM_addr); 1030 1031 // End of DW_TAG_subprogram. 1032 PushHalf(dbg_abbrev, 0); 1033 1034 // Start the debug_info section with the header information 1035 // 'unit_length' will be filled in later. 1036 PushWord(dbg_info, 0); 1037 1038 // 'version' - 3. 1039 PushHalf(dbg_info, 3); 1040 1041 // Offset into .debug_abbrev section (always 0). 1042 PushWord(dbg_info, 0); 1043 1044 // Address size: 4. 1045 dbg_info->push_back(4); 1046 1047 // Start the description for the compilation unit. 1048 // This uses tag 1. 1049 dbg_info->push_back(1); 1050 1051 // The language is Java. 1052 dbg_info->push_back(DW_LANG_Java); 1053 1054 // Leave space for low_pc and high_pc. 1055 int low_pc_offset = dbg_info->size(); 1056 PushWord(dbg_info, 0); 1057 PushWord(dbg_info, 0); 1058 1059 // Walk through the information in the method table, and enter into dbg_info. 1060 const std::vector<OatWriter::DebugInfo>& dbg = oat_writer->GetCFIMethodInfo(); 1061 uint32_t low_pc = 0xFFFFFFFFU; 1062 uint32_t high_pc = 0; 1063 1064 for (uint32_t i = 0; i < dbg.size(); i++) { 1065 const OatWriter::DebugInfo& info = dbg[i]; 1066 if (info.low_pc_ < low_pc) { 1067 low_pc = info.low_pc_; 1068 } 1069 if (info.high_pc_ > high_pc) { 1070 high_pc = info.high_pc_; 1071 } 1072 1073 // Start a new TAG: subroutine (2). 1074 dbg_info->push_back(2); 1075 1076 // Enter the name into the string table (and NUL terminate). 1077 uint32_t str_offset = dbg_str->size(); 1078 dbg_str->insert(dbg_str->end(), info.method_name_.begin(), info.method_name_.end()); 1079 dbg_str->push_back('\0'); 1080 1081 // Enter name, low_pc, high_pc. 1082 PushWord(dbg_info, str_offset); 1083 PushWord(dbg_info, info.low_pc_); 1084 PushWord(dbg_info, info.high_pc_); 1085 } 1086 1087 // One byte terminator 1088 dbg_info->push_back(0); 1089 1090 // We have now walked all the methods. Fill in lengths and low/high PCs. 1091 UpdateWord(dbg_info, 0, dbg_info->size() - 4); 1092 UpdateWord(dbg_info, low_pc_offset, low_pc); 1093 UpdateWord(dbg_info, low_pc_offset + 4, high_pc); 1094 } 1095 1096 } // namespace art 1097