Archive.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===- Archive.cpp - ar File Format implementation --------------*- 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// This file defines the ArchiveObjectFile class. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/Object/Archive.h" 15#include "llvm/ADT/APInt.h" 16#include "llvm/ADT/OwningPtr.h" 17#include "llvm/ADT/SmallString.h" 18#include "llvm/ADT/Twine.h" 19#include "llvm/Support/Endian.h" 20#include "llvm/Support/MemoryBuffer.h" 21 22using namespace llvm; 23using namespace object; 24 25static const char *const Magic = "!<arch>\n"; 26 27void Archive::anchor() { } 28 29StringRef ArchiveMemberHeader::getName() const { 30 char EndCond; 31 if (Name[0] == '/' || Name[0] == '#') 32 EndCond = ' '; 33 else 34 EndCond = '/'; 35 llvm::StringRef::size_type end = 36 llvm::StringRef(Name, sizeof(Name)).find(EndCond); 37 if (end == llvm::StringRef::npos) 38 end = sizeof(Name); 39 assert(end <= sizeof(Name) && end > 0); 40 // Don't include the EndCond if there is one. 41 return llvm::StringRef(Name, end); 42} 43 44uint32_t ArchiveMemberHeader::getSize() const { 45 uint32_t Ret; 46 if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret)) 47 llvm_unreachable("Size is not a decimal number."); 48 return Ret; 49} 50 51sys::fs::perms ArchiveMemberHeader::getAccessMode() const { 52 unsigned Ret; 53 if (StringRef(AccessMode, sizeof(AccessMode)).rtrim(" ").getAsInteger(8, Ret)) 54 llvm_unreachable("Access mode is not an octal number."); 55 return static_cast<sys::fs::perms>(Ret); 56} 57 58sys::TimeValue ArchiveMemberHeader::getLastModified() const { 59 unsigned Seconds; 60 if (StringRef(LastModified, sizeof(LastModified)).rtrim(" ") 61 .getAsInteger(10, Seconds)) 62 llvm_unreachable("Last modified time not a decimal number."); 63 64 sys::TimeValue Ret; 65 Ret.fromEpochTime(Seconds); 66 return Ret; 67} 68 69unsigned ArchiveMemberHeader::getUID() const { 70 unsigned Ret; 71 if (StringRef(UID, sizeof(UID)).rtrim(" ").getAsInteger(10, Ret)) 72 llvm_unreachable("UID time not a decimal number."); 73 return Ret; 74} 75 76unsigned ArchiveMemberHeader::getGID() const { 77 unsigned Ret; 78 if (StringRef(GID, sizeof(GID)).rtrim(" ").getAsInteger(10, Ret)) 79 llvm_unreachable("GID time not a decimal number."); 80 return Ret; 81} 82 83Archive::Child::Child(const Archive *Parent, const char *Start) 84 : Parent(Parent) { 85 if (!Start) 86 return; 87 88 const ArchiveMemberHeader *Header = 89 reinterpret_cast<const ArchiveMemberHeader *>(Start); 90 Data = StringRef(Start, sizeof(ArchiveMemberHeader) + Header->getSize()); 91 92 // Setup StartOfFile and PaddingBytes. 93 StartOfFile = sizeof(ArchiveMemberHeader); 94 // Don't include attached name. 95 StringRef Name = Header->getName(); 96 if (Name.startswith("#1/")) { 97 uint64_t NameSize; 98 if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) 99 llvm_unreachable("Long name length is not an integer"); 100 StartOfFile += NameSize; 101 } 102} 103 104Archive::Child Archive::Child::getNext() const { 105 size_t SpaceToSkip = Data.size(); 106 // If it's odd, add 1 to make it even. 107 if (SpaceToSkip & 1) 108 ++SpaceToSkip; 109 110 const char *NextLoc = Data.data() + SpaceToSkip; 111 112 // Check to see if this is past the end of the archive. 113 if (NextLoc >= Parent->Data->getBufferEnd()) 114 return Child(Parent, NULL); 115 116 return Child(Parent, NextLoc); 117} 118 119error_code Archive::Child::getName(StringRef &Result) const { 120 StringRef name = getRawName(); 121 // Check if it's a special name. 122 if (name[0] == '/') { 123 if (name.size() == 1) { // Linker member. 124 Result = name; 125 return object_error::success; 126 } 127 if (name.size() == 2 && name[1] == '/') { // String table. 128 Result = name; 129 return object_error::success; 130 } 131 // It's a long name. 132 // Get the offset. 133 std::size_t offset; 134 if (name.substr(1).rtrim(" ").getAsInteger(10, offset)) 135 llvm_unreachable("Long name offset is not an integer"); 136 const char *addr = Parent->StringTable->Data.begin() 137 + sizeof(ArchiveMemberHeader) 138 + offset; 139 // Verify it. 140 if (Parent->StringTable == Parent->child_end() 141 || addr < (Parent->StringTable->Data.begin() 142 + sizeof(ArchiveMemberHeader)) 143 || addr > (Parent->StringTable->Data.begin() 144 + sizeof(ArchiveMemberHeader) 145 + Parent->StringTable->getSize())) 146 return object_error::parse_failed; 147 148 // GNU long file names end with a /. 149 if (Parent->kind() == K_GNU) { 150 StringRef::size_type End = StringRef(addr).find('/'); 151 Result = StringRef(addr, End); 152 } else { 153 Result = addr; 154 } 155 return object_error::success; 156 } else if (name.startswith("#1/")) { 157 uint64_t name_size; 158 if (name.substr(3).rtrim(" ").getAsInteger(10, name_size)) 159 llvm_unreachable("Long name length is not an ingeter"); 160 Result = Data.substr(sizeof(ArchiveMemberHeader), name_size) 161 .rtrim(StringRef("\0", 1)); 162 return object_error::success; 163 } 164 // It's a simple name. 165 if (name[name.size() - 1] == '/') 166 Result = name.substr(0, name.size() - 1); 167 else 168 Result = name; 169 return object_error::success; 170} 171 172error_code Archive::Child::getMemoryBuffer(std::unique_ptr<MemoryBuffer> &Result, 173 bool FullPath) const { 174 StringRef Name; 175 if (error_code ec = getName(Name)) 176 return ec; 177 SmallString<128> Path; 178 Result.reset(MemoryBuffer::getMemBuffer( 179 getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + ")") 180 .toStringRef(Path) 181 : Name, 182 false)); 183 return error_code::success(); 184} 185 186error_code Archive::Child::getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, 187 bool FullPath) const { 188 std::unique_ptr<MemoryBuffer> MB; 189 error_code ec = getMemoryBuffer(MB, FullPath); 190 Result = std::move(MB); 191 return ec; 192} 193 194error_code Archive::Child::getAsBinary(std::unique_ptr<Binary> &Result, 195 LLVMContext *Context) const { 196 std::unique_ptr<Binary> ret; 197 std::unique_ptr<MemoryBuffer> Buff; 198 if (error_code ec = getMemoryBuffer(Buff)) 199 return ec; 200 ErrorOr<Binary *> BinaryOrErr = createBinary(Buff.release(), Context); 201 if (error_code EC = BinaryOrErr.getError()) 202 return EC; 203 Result.reset(BinaryOrErr.get()); 204 return object_error::success; 205} 206 207error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result, 208 LLVMContext *Context) const { 209 std::unique_ptr<Binary> B; 210 error_code ec = getAsBinary(B, Context); 211 Result = std::move(B); 212 return ec; 213} 214 215ErrorOr<Archive*> Archive::create(MemoryBuffer *Source) { 216 error_code EC; 217 std::unique_ptr<Archive> Ret(new Archive(Source, EC)); 218 if (EC) 219 return EC; 220 return Ret.release(); 221} 222 223Archive::Archive(MemoryBuffer *source, error_code &ec) 224 : Binary(Binary::ID_Archive, source), SymbolTable(child_end()) { 225 // Check for sufficient magic. 226 assert(source); 227 if (source->getBufferSize() < 8 || 228 StringRef(source->getBufferStart(), 8) != Magic) { 229 ec = object_error::invalid_file_type; 230 return; 231 } 232 233 // Get the special members. 234 child_iterator i = child_begin(false); 235 child_iterator e = child_end(); 236 237 if (i == e) { 238 ec = object_error::success; 239 return; 240 } 241 242 StringRef Name = i->getRawName(); 243 244 // Below is the pattern that is used to figure out the archive format 245 // GNU archive format 246 // First member : / (may exist, if it exists, points to the symbol table ) 247 // Second member : // (may exist, if it exists, points to the string table) 248 // Note : The string table is used if the filename exceeds 15 characters 249 // BSD archive format 250 // First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table) 251 // There is no string table, if the filename exceeds 15 characters or has a 252 // embedded space, the filename has #1/<size>, The size represents the size 253 // of the filename that needs to be read after the archive header 254 // COFF archive format 255 // First member : / 256 // Second member : / (provides a directory of symbols) 257 // Third member : // (may exist, if it exists, contains the string table) 258 // Note: Microsoft PE/COFF Spec 8.3 says that the third member is present 259 // even if the string table is empty. However, lib.exe does not in fact 260 // seem to create the third member if there's no member whose filename 261 // exceeds 15 characters. So the third member is optional. 262 263 if (Name == "__.SYMDEF") { 264 Format = K_BSD; 265 SymbolTable = i; 266 ++i; 267 FirstRegular = i; 268 ec = object_error::success; 269 return; 270 } 271 272 if (Name.startswith("#1/")) { 273 Format = K_BSD; 274 // We know this is BSD, so getName will work since there is no string table. 275 ec = i->getName(Name); 276 if (ec) 277 return; 278 if (Name == "__.SYMDEF SORTED") { 279 SymbolTable = i; 280 ++i; 281 } 282 FirstRegular = i; 283 return; 284 } 285 286 if (Name == "/") { 287 SymbolTable = i; 288 289 ++i; 290 if (i == e) { 291 ec = object_error::parse_failed; 292 return; 293 } 294 Name = i->getRawName(); 295 } 296 297 if (Name == "//") { 298 Format = K_GNU; 299 StringTable = i; 300 ++i; 301 FirstRegular = i; 302 ec = object_error::success; 303 return; 304 } 305 306 if (Name[0] != '/') { 307 Format = K_GNU; 308 FirstRegular = i; 309 ec = object_error::success; 310 return; 311 } 312 313 if (Name != "/") { 314 ec = object_error::parse_failed; 315 return; 316 } 317 318 Format = K_COFF; 319 SymbolTable = i; 320 321 ++i; 322 if (i == e) { 323 FirstRegular = i; 324 ec = object_error::success; 325 return; 326 } 327 328 Name = i->getRawName(); 329 330 if (Name == "//") { 331 StringTable = i; 332 ++i; 333 } 334 335 FirstRegular = i; 336 ec = object_error::success; 337} 338 339Archive::child_iterator Archive::child_begin(bool SkipInternal) const { 340 if (Data->getBufferSize() == 8) // empty archive. 341 return child_end(); 342 343 if (SkipInternal) 344 return FirstRegular; 345 346 const char *Loc = Data->getBufferStart() + strlen(Magic); 347 Child c(this, Loc); 348 return c; 349} 350 351Archive::child_iterator Archive::child_end() const { 352 return Child(this, NULL); 353} 354 355error_code Archive::Symbol::getName(StringRef &Result) const { 356 Result = StringRef(Parent->SymbolTable->getBuffer().begin() + StringIndex); 357 return object_error::success; 358} 359 360error_code Archive::Symbol::getMember(child_iterator &Result) const { 361 const char *Buf = Parent->SymbolTable->getBuffer().begin(); 362 const char *Offsets = Buf + 4; 363 uint32_t Offset = 0; 364 if (Parent->kind() == K_GNU) { 365 Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets) 366 + SymbolIndex); 367 } else if (Parent->kind() == K_BSD) { 368 llvm_unreachable("BSD format is not supported"); 369 } else { 370 uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); 371 372 // Skip offsets. 373 Buf += sizeof(support::ulittle32_t) 374 + (MemberCount * sizeof(support::ulittle32_t)); 375 376 uint32_t SymbolCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); 377 378 if (SymbolIndex >= SymbolCount) 379 return object_error::parse_failed; 380 381 // Skip SymbolCount to get to the indices table. 382 const char *Indices = Buf + sizeof(support::ulittle32_t); 383 384 // Get the index of the offset in the file member offset table for this 385 // symbol. 386 uint16_t OffsetIndex = 387 *(reinterpret_cast<const support::ulittle16_t*>(Indices) 388 + SymbolIndex); 389 // Subtract 1 since OffsetIndex is 1 based. 390 --OffsetIndex; 391 392 if (OffsetIndex >= MemberCount) 393 return object_error::parse_failed; 394 395 Offset = *(reinterpret_cast<const support::ulittle32_t*>(Offsets) 396 + OffsetIndex); 397 } 398 399 const char *Loc = Parent->getData().begin() + Offset; 400 Result = Child(Parent, Loc); 401 402 return object_error::success; 403} 404 405Archive::Symbol Archive::Symbol::getNext() const { 406 Symbol t(*this); 407 // Go to one past next null. 408 t.StringIndex = 409 Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; 410 ++t.SymbolIndex; 411 return t; 412} 413 414Archive::symbol_iterator Archive::symbol_begin() const { 415 if (!hasSymbolTable()) 416 return symbol_iterator(Symbol(this, 0, 0)); 417 418 const char *buf = SymbolTable->getBuffer().begin(); 419 if (kind() == K_GNU) { 420 uint32_t symbol_count = 0; 421 symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); 422 buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); 423 } else if (kind() == K_BSD) { 424 llvm_unreachable("BSD archive format is not supported"); 425 } else { 426 uint32_t member_count = 0; 427 uint32_t symbol_count = 0; 428 member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); 429 buf += 4 + (member_count * 4); // Skip offsets. 430 symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); 431 buf += 4 + (symbol_count * 2); // Skip indices. 432 } 433 uint32_t string_start_offset = buf - SymbolTable->getBuffer().begin(); 434 return symbol_iterator(Symbol(this, 0, string_start_offset)); 435} 436 437Archive::symbol_iterator Archive::symbol_end() const { 438 if (!hasSymbolTable()) 439 return symbol_iterator(Symbol(this, 0, 0)); 440 441 const char *buf = SymbolTable->getBuffer().begin(); 442 uint32_t symbol_count = 0; 443 if (kind() == K_GNU) { 444 symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); 445 } else if (kind() == K_BSD) { 446 llvm_unreachable("BSD archive format is not supported"); 447 } else { 448 uint32_t member_count = 0; 449 member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); 450 buf += 4 + (member_count * 4); // Skip offsets. 451 symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); 452 } 453 return symbol_iterator( 454 Symbol(this, symbol_count, 0)); 455} 456 457Archive::child_iterator Archive::findSym(StringRef name) const { 458 Archive::symbol_iterator bs = symbol_begin(); 459 Archive::symbol_iterator es = symbol_end(); 460 Archive::child_iterator result; 461 462 StringRef symname; 463 for (; bs != es; ++bs) { 464 if (bs->getName(symname)) 465 return child_end(); 466 if (symname == name) { 467 if (bs->getMember(result)) 468 return child_end(); 469 return result; 470 } 471 } 472 return child_end(); 473} 474 475bool Archive::hasSymbolTable() const { 476 return SymbolTable != child_end(); 477} 478