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
This commit is contained in:
Brian Gaeke
2003-12-11 00:38:04 +00:00
parent 27f7a71a25
commit 3c09636588
3 changed files with 129 additions and 150 deletions

View File

@ -44,10 +44,12 @@ namespace {
}; };
} }
// getObjectType - Determine the type of object that this header represents. /// getObjectType - Determine the type of object that this header represents.
// This is capable of parsing the variety of special sections used for various /// This is capable of parsing the variety of special sections used for various
// purposes. /// purposes.
static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) { ///
static enum ObjectType getObjectType(ar_hdr *H, unsigned char *MemberData,
unsigned Size) {
// Check for sections with special names... // Check for sections with special names...
if (!memcmp(H->name, "__.SYMDEF ", 16)) if (!memcmp(H->name, "__.SYMDEF ", 16))
return ArchiveSymbolTable; return ArchiveSymbolTable;
@ -55,44 +57,17 @@ static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) {
return SVR4LongFilename; return SVR4LongFilename;
// Check to see if it looks like an llvm object file... // 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 UserObject;
return Unknown; return Unknown;
} }
static inline bool Error(std::string *ErrorStr, const char *Message) { static inline bool Error(std::string *ErrorStr, const char *Message) {
if (ErrorStr) *ErrorStr = Message; if (ErrorStr) *ErrorStr = Message;
return true; 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, static bool ParseSymbolTableSection(unsigned char *Buffer, unsigned Size,
std::string *S) { std::string *S) {
// Currently not supported (succeeds without doing anything) // Currently not supported (succeeds without doing anything)
@ -111,40 +86,58 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
while (Length >= sizeof(ar_hdr)) { while (Length >= sizeof(ar_hdr)) {
ar_hdr *Hdr = (ar_hdr*)Buffer; ar_hdr *Hdr = (ar_hdr*)Buffer;
unsigned Size = atoi(Hdr->size); unsigned SizeFromHeader = atoi(Hdr->size);
if (Size+sizeof(ar_hdr) > Length) if (SizeFromHeader + sizeof(ar_hdr) > Length)
return Error(ErrorStr, "invalid record length in archive file!"); return Error(ErrorStr, "invalid record length in archive file!");
unsigned char *MemberData = Buffer + sizeof(ar_hdr);
unsigned MemberSize = SizeFromHeader;
// Get name of archive member. // Get name of archive member.
char *startp = Hdr->name; char *startp = Hdr->name;
char *endp = strchr (startp, '/'); char *endp = (char *) memchr (startp, '/', sizeof(ar_hdr));
if (startp == endp && isdigit (Hdr->name[1])) { if (memcmp (Hdr->name, "#1/", 3) == 0) {
// Long filenames are abbreviated as "/I", where I is a decimal // 4.4BSD/MacOSX long filenames are abbreviated as "#1/L", where L is an
// index into the LongFilenames vector. // ASCII-coded decimal number representing the length of the name buffer,
unsigned Index = atoi (&Hdr->name[1]); // which is prepended to the archive member's contents.
assert (LongFilenames.size () > Index unsigned NameLength = atoi (&Hdr->name[3]);
&& "Long filename for archive member not found"); startp = (char *) MemberData;
startp = &LongFilenames[Index]; 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, '/'); 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 MemberName (startp, endp);
std::string FullMemberName = ArchiveName + "(" + MemberName + ")"; std::string FullMemberName = ArchiveName + "(" + MemberName + ")";
switch (getObjectType(Hdr, Size)) { switch (getObjectType(Hdr, MemberData, MemberSize)) {
case SVR4LongFilename: case SVR4LongFilename:
// If this is a long filename section, read all of the file names into the // If this is a long filename section, read all of the file names into the
// LongFilenames vector. // LongFilenames vector.
LongFilenames.assign (Buffer+sizeof(ar_hdr), Buffer+sizeof(ar_hdr)+Size); LongFilenames.assign (MemberData, MemberData + MemberSize);
break; break;
case UserObject: { case UserObject: {
Module *M = ParseBytecodeBuffer(Buffer+sizeof(ar_hdr), Size, Module *M = ParseBytecodeBuffer(MemberData, MemberSize,
FullMemberName, ErrorStr); FullMemberName, ErrorStr);
if (!M) return true; if (!M) return true;
Objects.push_back(M); Objects.push_back(M);
break; break;
} }
case ArchiveSymbolTable: case ArchiveSymbolTable:
if (ParseSymbolTableSection(Buffer+sizeof(ar_hdr), Size, ErrorStr)) if (ParseSymbolTableSection(MemberData, MemberSize, ErrorStr))
return true; return true;
break; break;
default: default:
@ -153,10 +146,10 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
break; // Just ignore unknown files. break; // Just ignore unknown files.
} }
// Round Size up to an even number... // Round SizeFromHeader up to an even number...
Size = (Size+1)/2*2; SizeFromHeader = (SizeFromHeader+1)/2*2;
Buffer += sizeof(ar_hdr)+Size; // Move to the next entry Buffer += sizeof(ar_hdr)+SizeFromHeader; // Move to the next entry
Length -= sizeof(ar_hdr)+Size; Length -= sizeof(ar_hdr)+SizeFromHeader;
} }
return Length != 0; return Length != 0;

View File

@ -44,10 +44,12 @@ namespace {
}; };
} }
// getObjectType - Determine the type of object that this header represents. /// getObjectType - Determine the type of object that this header represents.
// This is capable of parsing the variety of special sections used for various /// This is capable of parsing the variety of special sections used for various
// purposes. /// purposes.
static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) { ///
static enum ObjectType getObjectType(ar_hdr *H, unsigned char *MemberData,
unsigned Size) {
// Check for sections with special names... // Check for sections with special names...
if (!memcmp(H->name, "__.SYMDEF ", 16)) if (!memcmp(H->name, "__.SYMDEF ", 16))
return ArchiveSymbolTable; return ArchiveSymbolTable;
@ -55,44 +57,17 @@ static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) {
return SVR4LongFilename; return SVR4LongFilename;
// Check to see if it looks like an llvm object file... // 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 UserObject;
return Unknown; return Unknown;
} }
static inline bool Error(std::string *ErrorStr, const char *Message) { static inline bool Error(std::string *ErrorStr, const char *Message) {
if (ErrorStr) *ErrorStr = Message; if (ErrorStr) *ErrorStr = Message;
return true; 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, static bool ParseSymbolTableSection(unsigned char *Buffer, unsigned Size,
std::string *S) { std::string *S) {
// Currently not supported (succeeds without doing anything) // Currently not supported (succeeds without doing anything)
@ -111,40 +86,58 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
while (Length >= sizeof(ar_hdr)) { while (Length >= sizeof(ar_hdr)) {
ar_hdr *Hdr = (ar_hdr*)Buffer; ar_hdr *Hdr = (ar_hdr*)Buffer;
unsigned Size = atoi(Hdr->size); unsigned SizeFromHeader = atoi(Hdr->size);
if (Size+sizeof(ar_hdr) > Length) if (SizeFromHeader + sizeof(ar_hdr) > Length)
return Error(ErrorStr, "invalid record length in archive file!"); return Error(ErrorStr, "invalid record length in archive file!");
unsigned char *MemberData = Buffer + sizeof(ar_hdr);
unsigned MemberSize = SizeFromHeader;
// Get name of archive member. // Get name of archive member.
char *startp = Hdr->name; char *startp = Hdr->name;
char *endp = strchr (startp, '/'); char *endp = (char *) memchr (startp, '/', sizeof(ar_hdr));
if (startp == endp && isdigit (Hdr->name[1])) { if (memcmp (Hdr->name, "#1/", 3) == 0) {
// Long filenames are abbreviated as "/I", where I is a decimal // 4.4BSD/MacOSX long filenames are abbreviated as "#1/L", where L is an
// index into the LongFilenames vector. // ASCII-coded decimal number representing the length of the name buffer,
unsigned Index = atoi (&Hdr->name[1]); // which is prepended to the archive member's contents.
assert (LongFilenames.size () > Index unsigned NameLength = atoi (&Hdr->name[3]);
&& "Long filename for archive member not found"); startp = (char *) MemberData;
startp = &LongFilenames[Index]; 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, '/'); 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 MemberName (startp, endp);
std::string FullMemberName = ArchiveName + "(" + MemberName + ")"; std::string FullMemberName = ArchiveName + "(" + MemberName + ")";
switch (getObjectType(Hdr, Size)) { switch (getObjectType(Hdr, MemberData, MemberSize)) {
case SVR4LongFilename: case SVR4LongFilename:
// If this is a long filename section, read all of the file names into the // If this is a long filename section, read all of the file names into the
// LongFilenames vector. // LongFilenames vector.
LongFilenames.assign (Buffer+sizeof(ar_hdr), Buffer+sizeof(ar_hdr)+Size); LongFilenames.assign (MemberData, MemberData + MemberSize);
break; break;
case UserObject: { case UserObject: {
Module *M = ParseBytecodeBuffer(Buffer+sizeof(ar_hdr), Size, Module *M = ParseBytecodeBuffer(MemberData, MemberSize,
FullMemberName, ErrorStr); FullMemberName, ErrorStr);
if (!M) return true; if (!M) return true;
Objects.push_back(M); Objects.push_back(M);
break; break;
} }
case ArchiveSymbolTable: case ArchiveSymbolTable:
if (ParseSymbolTableSection(Buffer+sizeof(ar_hdr), Size, ErrorStr)) if (ParseSymbolTableSection(MemberData, MemberSize, ErrorStr))
return true; return true;
break; break;
default: default:
@ -153,10 +146,10 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
break; // Just ignore unknown files. break; // Just ignore unknown files.
} }
// Round Size up to an even number... // Round SizeFromHeader up to an even number...
Size = (Size+1)/2*2; SizeFromHeader = (SizeFromHeader+1)/2*2;
Buffer += sizeof(ar_hdr)+Size; // Move to the next entry Buffer += sizeof(ar_hdr)+SizeFromHeader; // Move to the next entry
Length -= sizeof(ar_hdr)+Size; Length -= sizeof(ar_hdr)+SizeFromHeader;
} }
return Length != 0; return Length != 0;

View File

@ -44,10 +44,12 @@ namespace {
}; };
} }
// getObjectType - Determine the type of object that this header represents. /// getObjectType - Determine the type of object that this header represents.
// This is capable of parsing the variety of special sections used for various /// This is capable of parsing the variety of special sections used for various
// purposes. /// purposes.
static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) { ///
static enum ObjectType getObjectType(ar_hdr *H, unsigned char *MemberData,
unsigned Size) {
// Check for sections with special names... // Check for sections with special names...
if (!memcmp(H->name, "__.SYMDEF ", 16)) if (!memcmp(H->name, "__.SYMDEF ", 16))
return ArchiveSymbolTable; return ArchiveSymbolTable;
@ -55,44 +57,17 @@ static enum ObjectType getObjectType(ar_hdr *H, unsigned Size) {
return SVR4LongFilename; return SVR4LongFilename;
// Check to see if it looks like an llvm object file... // 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 UserObject;
return Unknown; return Unknown;
} }
static inline bool Error(std::string *ErrorStr, const char *Message) { static inline bool Error(std::string *ErrorStr, const char *Message) {
if (ErrorStr) *ErrorStr = Message; if (ErrorStr) *ErrorStr = Message;
return true; 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, static bool ParseSymbolTableSection(unsigned char *Buffer, unsigned Size,
std::string *S) { std::string *S) {
// Currently not supported (succeeds without doing anything) // Currently not supported (succeeds without doing anything)
@ -111,40 +86,58 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
while (Length >= sizeof(ar_hdr)) { while (Length >= sizeof(ar_hdr)) {
ar_hdr *Hdr = (ar_hdr*)Buffer; ar_hdr *Hdr = (ar_hdr*)Buffer;
unsigned Size = atoi(Hdr->size); unsigned SizeFromHeader = atoi(Hdr->size);
if (Size+sizeof(ar_hdr) > Length) if (SizeFromHeader + sizeof(ar_hdr) > Length)
return Error(ErrorStr, "invalid record length in archive file!"); return Error(ErrorStr, "invalid record length in archive file!");
unsigned char *MemberData = Buffer + sizeof(ar_hdr);
unsigned MemberSize = SizeFromHeader;
// Get name of archive member. // Get name of archive member.
char *startp = Hdr->name; char *startp = Hdr->name;
char *endp = strchr (startp, '/'); char *endp = (char *) memchr (startp, '/', sizeof(ar_hdr));
if (startp == endp && isdigit (Hdr->name[1])) { if (memcmp (Hdr->name, "#1/", 3) == 0) {
// Long filenames are abbreviated as "/I", where I is a decimal // 4.4BSD/MacOSX long filenames are abbreviated as "#1/L", where L is an
// index into the LongFilenames vector. // ASCII-coded decimal number representing the length of the name buffer,
unsigned Index = atoi (&Hdr->name[1]); // which is prepended to the archive member's contents.
assert (LongFilenames.size () > Index unsigned NameLength = atoi (&Hdr->name[3]);
&& "Long filename for archive member not found"); startp = (char *) MemberData;
startp = &LongFilenames[Index]; 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, '/'); 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 MemberName (startp, endp);
std::string FullMemberName = ArchiveName + "(" + MemberName + ")"; std::string FullMemberName = ArchiveName + "(" + MemberName + ")";
switch (getObjectType(Hdr, Size)) { switch (getObjectType(Hdr, MemberData, MemberSize)) {
case SVR4LongFilename: case SVR4LongFilename:
// If this is a long filename section, read all of the file names into the // If this is a long filename section, read all of the file names into the
// LongFilenames vector. // LongFilenames vector.
LongFilenames.assign (Buffer+sizeof(ar_hdr), Buffer+sizeof(ar_hdr)+Size); LongFilenames.assign (MemberData, MemberData + MemberSize);
break; break;
case UserObject: { case UserObject: {
Module *M = ParseBytecodeBuffer(Buffer+sizeof(ar_hdr), Size, Module *M = ParseBytecodeBuffer(MemberData, MemberSize,
FullMemberName, ErrorStr); FullMemberName, ErrorStr);
if (!M) return true; if (!M) return true;
Objects.push_back(M); Objects.push_back(M);
break; break;
} }
case ArchiveSymbolTable: case ArchiveSymbolTable:
if (ParseSymbolTableSection(Buffer+sizeof(ar_hdr), Size, ErrorStr)) if (ParseSymbolTableSection(MemberData, MemberSize, ErrorStr))
return true; return true;
break; break;
default: default:
@ -153,10 +146,10 @@ static bool ReadArchiveBuffer(const std::string &ArchiveName,
break; // Just ignore unknown files. break; // Just ignore unknown files.
} }
// Round Size up to an even number... // Round SizeFromHeader up to an even number...
Size = (Size+1)/2*2; SizeFromHeader = (SizeFromHeader+1)/2*2;
Buffer += sizeof(ar_hdr)+Size; // Move to the next entry Buffer += sizeof(ar_hdr)+SizeFromHeader; // Move to the next entry
Length -= sizeof(ar_hdr)+Size; Length -= sizeof(ar_hdr)+SizeFromHeader;
} }
return Length != 0; return Length != 0;