Section* BinObject::AppendSection(llvm::StringRef name, SourceLocation source, Diagnostic& diags) { bool bss = (name == ".bss"); bool code = (name == ".text"); Section* section = new Section(name, code, bss, source); m_object.AppendSection(std::auto_ptr<Section>(section)); // Initialize section data and symbols. std::auto_ptr<BinSection> bsd(new BinSection()); SymbolRef start = m_object.getSymbol(("section."+name+".start").str()); if (start->okToDeclare(Symbol::EXTERN)) { start->Declare(Symbol::EXTERN); start->setDeclSource(source); } start->AddAssocData(std::auto_ptr<BinSymbol> (new BinSymbol(*section, *bsd, BinSymbol::START))); SymbolRef vstart = m_object.getSymbol(("section."+name+".vstart").str()); if (vstart->okToDeclare(Symbol::EXTERN)) { vstart->Declare(Symbol::EXTERN); vstart->setDeclSource(source); } vstart->AddAssocData(std::auto_ptr<BinSymbol> (new BinSymbol(*section, *bsd, BinSymbol::VSTART))); SymbolRef length = m_object.getSymbol(("section."+name+".length").str()); if (length->okToDeclare(Symbol::EXTERN)) { length->Declare(Symbol::EXTERN); length->setDeclSource(source); } length->AddAssocData(std::auto_ptr<BinSymbol> (new BinSymbol(*section, *bsd, BinSymbol::LENGTH))); section->AddAssocData(std::auto_ptr<BinSection>(bsd.release())); return section; }
bool ElfConfig::ReadSymbolTable(const MemoryBuffer& in, const ElfSection& symtab_sect, ElfSymtab& symtab, Object& object, const StringTable& strtab, Section* sections[], DiagnosticsEngine& diags) const { ElfSize symsize = symtab_sect.getEntSize(); if (symsize == 0) { diags.Report(SourceLocation(), diag::err_symbol_entity_size_zero); return false; } unsigned long size = symtab_sect.getSize().getUInt(); // Symbol table always starts with null entry symtab.push_back(SymbolRef(0)); ElfSymbolIndex index = 1; for (unsigned long pos=symsize; pos<size; pos += symsize, ++index) { std::auto_ptr<ElfSymbol> elfsym( new ElfSymbol(*this, in, symtab_sect, index, sections, diags)); if (diags.hasErrorOccurred()) return false; SymbolRef sym = elfsym->CreateSymbol(object, strtab); symtab.push_back(sym); if (sym) sym->AddAssocData(elfsym); // Associate symbol data with symbol } return true; }
bool XdfObject::Read(SourceManager& sm, Diagnostic& diags) { const llvm::MemoryBuffer& in = *sm.getBuffer(sm.getMainFileID()); InputBuffer inbuf(in); inbuf.setLittleEndian(); // Read object header if (inbuf.getReadableSize() < FILEHEAD_SIZE) { diags.Report(SourceLocation(), diag::err_object_header_unreadable); return false; } unsigned long magic = ReadU32(inbuf); if (magic != XDF_MAGIC) { diags.Report(SourceLocation(), diag::err_not_file_type) << "XDF"; return false; } unsigned long scnum = ReadU32(inbuf); unsigned long symnum = ReadU32(inbuf); unsigned long headers_len = ReadU32(inbuf); if (inbuf.getReadableSize() < headers_len) { diags.Report(SourceLocation(), diag::err_xdf_headers_unreadable); return false; } unsigned long section_offset = FILEHEAD_SIZE; unsigned long symtab_offset = section_offset + SECTHEAD_SIZE*scnum; unsigned long strtab_offset = symtab_offset + SYMBOL_SIZE*symnum; ReadString read_string(in, strtab_offset, FILEHEAD_SIZE+headers_len-strtab_offset, diags); // Storage for nrelocs, indexed by section number std::vector<unsigned long> sects_nrelocs; sects_nrelocs.reserve(scnum); // Create sections for (unsigned long i=0; i<scnum; ++i) { // Start with symbol=0 as it's not created yet; updated later. std::auto_ptr<XdfSection> xsect(new XdfSection(SymbolRef(0))); unsigned long name_sym_index; IntNum lma, vma; unsigned long align; bool bss; unsigned long filepos; unsigned long nrelocs; xsect->Read(in, section_offset+SECTHEAD_SIZE*i, &name_sym_index, &lma, &vma, &align, &bss, &filepos, &nrelocs); xsect->scnum = i; // get section name from section symbol entry inbuf.setPosition(symtab_offset+name_sym_index*SYMBOL_SIZE+8); llvm::StringRef sectname = read_string(ReadU32(inbuf)); std::auto_ptr<Section> section( new Section(sectname, xsect->bits != 0, bss, SourceLocation())); section->setFilePos(filepos); section->setVMA(vma); section->setLMA(lma); if (bss) { Bytecode& gap = section->AppendGap(xsect->size, SourceLocation()); Diagnostic nodiags(0); gap.CalcLen(0, nodiags); // force length calculation of gap } else { // Read section data inbuf.setPosition(filepos); if (inbuf.getReadableSize() < xsect->size) { diags.Report(SourceLocation(), diag::err_section_data_unreadable) << sectname; return false; } section->bytecodes_front().getFixed().Write(inbuf.Read(xsect->size), xsect->size); } // Associate section data with section section->AddAssocData(xsect); // Add section to object m_object.AppendSection(section); sects_nrelocs.push_back(nrelocs); } // Create symbols inbuf.setPosition(symtab_offset); for (unsigned long i=0; i<symnum; ++i) { unsigned long sym_scnum = ReadU32(inbuf); // section number unsigned long value = ReadU32(inbuf); // value llvm::StringRef symname = read_string(ReadU32(inbuf));// name unsigned long flags = ReadU32(inbuf); // flags SymbolRef sym = m_object.getSymbol(symname); if ((flags & XdfSymbol::XDF_GLOBAL) != 0) sym->Declare(Symbol::GLOBAL); else if ((flags & XdfSymbol::XDF_EXTERN) != 0) sym->Declare(Symbol::EXTERN); if ((flags & XdfSymbol::XDF_EQU) != 0) sym->DefineEqu(Expr(value)); else if (sym_scnum < scnum) { Section& sect = m_object.getSection(sym_scnum); Location loc = {§.bytecodes_front(), value}; sym->DefineLabel(loc); } // Save index in symrec data sym->AddAssocData(std::auto_ptr<XdfSymbol>(new XdfSymbol(i))); } // Update section symbol info, and create section relocations std::vector<unsigned long>::iterator nrelocsi = sects_nrelocs.begin(); for (Object::section_iterator sect=m_object.sections_begin(), end=m_object.sections_end(); sect != end; ++sect, ++nrelocsi) { XdfSection* xsect = sect->getAssocData<XdfSection>(); assert(xsect != 0); // Read relocations inbuf.setPosition(xsect->relptr); if (inbuf.getReadableSize() < (*nrelocsi) * RELOC_SIZE) { diags.Report(SourceLocation(), diag::err_section_relocs_unreadable) << sect->getName(); return false; } for (unsigned long i=0; i<(*nrelocsi); ++i) { unsigned long addr = ReadU32(inbuf); unsigned long sym_index = ReadU32(inbuf); unsigned long basesym_index = ReadU32(inbuf); XdfReloc::Type type = static_cast<XdfReloc::Type>(ReadU8(inbuf)); XdfReloc::Size size = static_cast<XdfReloc::Size>(ReadU8(inbuf)); unsigned char shift = ReadU8(inbuf); ReadU8(inbuf); // flags; ignored SymbolRef sym = m_object.getSymbol(sym_index); SymbolRef basesym(0); if (type == XdfReloc::XDF_WRT) basesym = m_object.getSymbol(basesym_index); sect->AddReloc(std::auto_ptr<Reloc>( new XdfReloc(addr, sym, basesym, type, size, shift))); } } if (diags.hasErrorOccurred()) return false; return true; }