summaryrefslogtreecommitdiff
path: root/lib/Archive
diff options
context:
space:
mode:
authorBrian Gaeke <gaeke@uiuc.edu>2003-12-11 00:38:04 +0000
committerBrian Gaeke <gaeke@uiuc.edu>2003-12-11 00:38:04 +0000
commit3c0963658820a2e254e00b229fff2b7654aff3e4 (patch)
tree6ff34e5107d854e72c4fd05b1bc890a54b0df28d /lib/Archive
parent27f7a71a252ba146b04a1610a3d1c05729b07012 (diff)
In getObjectType(), doxygenify comment, and take a pointer to the
beginning of the archive member data as an argument. Get rid of ParseLongFilenameSection(), which is dead. In ReadArchiveBuffer(), implement support for 4.4BSD/MacOSX long filenames. This is kind of invasive, because they prepend the long filename to the archive member data, and then lie about the size. So we have to keep track of the real size. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10392 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Archive')
-rw-r--r--lib/Archive/ArchiveReader.cpp93
1 files changed, 43 insertions, 50 deletions
diff --git a/lib/Archive/ArchiveReader.cpp b/lib/Archive/ArchiveReader.cpp
index d93fd8c9df6..21f1f7d8483 100644
--- a/lib/Archive/ArchiveReader.cpp
+++ b/lib/Archive/ArchiveReader.cpp
@@ -44,10 +44,12 @@ namespace {
};
}
-// getObjectType - Determine the type of object that this header represents.
-// This is capable of parsing the variety of special sections used for various
-// purposes.
-static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) {
+/// getObjectType - Determine the type of object that this header represents.
+/// This is capable of parsing the variety of special sections used for various
+/// purposes.
+///
+static enum ObjectType getObjectType(ar_hdr *H, unsigned char *MemberData,
+ unsigned Size) {
// Check for sections with special names...
if (!memcmp(H->name, "__.SYMDEF ", 16))
return ArchiveSymbolTable;
@@ -55,44 +57,17 @@ static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) {
return SVR4LongFilename;
// Check to see if it looks like an llvm object file...
- if (Size >= 4 && !memcmp(H+1, "llvm", 4))
+ if (Size >= 4 && !memcmp(MemberData, "llvm", 4))
return UserObject;
return Unknown;
}
-
static inline bool Error(std::string *ErrorStr, const char *Message) {
if (ErrorStr) *ErrorStr = Message;
return true;
}
-static bool ParseLongFilenameSection(unsigned char *Buffer, unsigned Size,
- std::vector<std::string> &LongFilenames,
- std::string *S) {
- if (!LongFilenames.empty())
- return Error(S, "archive file contains multiple long filename entries");
-
- while (Size) {
- // Long filename entries are newline delimited to keep the archive readable.
- unsigned char *Ptr = (unsigned char*)memchr(Buffer, '\n', Size);
- if (Ptr == 0)
- return Error(S, "archive long filename entry doesn't end with newline!");
- assert(*Ptr == '\n');
-
- if (Ptr == Buffer) break; // Last entry contains just a newline.
-
- unsigned char *End = Ptr;
- if (End[-1] == '/') --End; // Remove trailing / from name
-
- LongFilenames.push_back(std::string(Buffer, End));
- Size -= Ptr-Buffer+1;
- Buffer = Ptr+1;
- }
-
- return false;
-}
-
static bool ParseSymbolTableSection(unsigned char *Buffer, unsigned Size,
std::string *S) {
// Currently not supported (succeeds without doing anything)
@@ -111,40 +86,58 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
while (Length >= sizeof(ar_hdr)) {
ar_hdr *Hdr = (ar_hdr*)Buffer;
- unsigned Size = atoi(Hdr->size);
- if (Size+sizeof(ar_hdr) > Length)
+ unsigned SizeFromHeader = atoi(Hdr->size);
+ if (SizeFromHeader + sizeof(ar_hdr) > Length)
return Error(ErrorStr, "invalid record length in archive file!");
+ unsigned char *MemberData = Buffer + sizeof(ar_hdr);
+ unsigned MemberSize = SizeFromHeader;
// Get name of archive member.
char *startp = Hdr->name;
- char *endp = strchr (startp, '/');
- if (startp == endp && isdigit (Hdr->name[1])) {
- // Long filenames are abbreviated as "/I", where I is a decimal
- // index into the LongFilenames vector.
- unsigned Index = atoi (&Hdr->name[1]);
- assert (LongFilenames.size () > Index
- && "Long filename for archive member not found");
- startp = &LongFilenames[Index];
+ char *endp = (char *) memchr (startp, '/', sizeof(ar_hdr));
+ if (memcmp (Hdr->name, "#1/", 3) == 0) {
+ // 4.4BSD/MacOSX long filenames are abbreviated as "#1/L", where L is an
+ // ASCII-coded decimal number representing the length of the name buffer,
+ // which is prepended to the archive member's contents.
+ unsigned NameLength = atoi (&Hdr->name[3]);
+ startp = (char *) MemberData;
+ endp = startp + NameLength;
+ MemberData += NameLength;
+ MemberSize -= NameLength;
+ } else if (startp == endp && isdigit (Hdr->name[1])) {
+ // SVR4 long filenames are abbreviated as "/I", where I is
+ // an ASCII-coded decimal index into the LongFilenames vector.
+ unsigned NameIndex = atoi (&Hdr->name[1]);
+ assert (LongFilenames.size () > NameIndex
+ && "SVR4-style long filename for archive member not found");
+ startp = &LongFilenames[NameIndex];
endp = strchr (startp, '/');
}
+ if (!endp) {
+ // 4.4BSD/MacOSX *short* filenames are not guaranteed to have a
+ // terminator. Start at the end of the field and backtrack over spaces.
+ endp = startp + sizeof(Hdr->name);
+ while (endp[-1] == ' ')
+ --endp;
+ }
std::string MemberName (startp, endp);
std::string FullMemberName = ArchiveName + "(" + MemberName + ")";
- switch (getObjectType(Hdr, Size)) {
+ switch (getObjectType(Hdr, MemberData, MemberSize)) {
case SVR4LongFilename:
// If this is a long filename section, read all of the file names into the
// LongFilenames vector.
- LongFilenames.assign (Buffer+sizeof(ar_hdr), Buffer+sizeof(ar_hdr)+Size);
+ LongFilenames.assign (MemberData, MemberData + MemberSize);
break;
case UserObject: {
- Module *M = ParseBytecodeBuffer(Buffer+sizeof(ar_hdr), Size,
+ Module *M = ParseBytecodeBuffer(MemberData, MemberSize,
FullMemberName, ErrorStr);
if (!M) return true;
Objects.push_back(M);
break;
}
case ArchiveSymbolTable:
- if (ParseSymbolTableSection(Buffer+sizeof(ar_hdr), Size, ErrorStr))
+ if (ParseSymbolTableSection(MemberData, MemberSize, ErrorStr))
return true;
break;
default:
@@ -153,10 +146,10 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
break; // Just ignore unknown files.
}
- // Round Size up to an even number...
- Size = (Size+1)/2*2;
- Buffer += sizeof(ar_hdr)+Size; // Move to the next entry
- Length -= sizeof(ar_hdr)+Size;
+ // Round SizeFromHeader up to an even number...
+ SizeFromHeader = (SizeFromHeader+1)/2*2;
+ Buffer += sizeof(ar_hdr)+SizeFromHeader; // Move to the next entry
+ Length -= sizeof(ar_hdr)+SizeFromHeader;
}
return Length != 0;