[llvm] 4cc7c74 - [AIX] Align the content of an xcoff object file which has auxiliary header in big archive.
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 6 08:35:45 PDT 2023
Author: zhijian
Date: 2023-09-06T11:35:18-04:00
New Revision: 4cc7c749c31e59459b585f8c69f7fa6a9ccb3440
URL: https://github.com/llvm/llvm-project/commit/4cc7c749c31e59459b585f8c69f7fa6a9ccb3440
DIFF: https://github.com/llvm/llvm-project/commit/4cc7c749c31e59459b585f8c69f7fa6a9ccb3440.diff
LOG: [AIX] Align the content of an xcoff object file which has auxiliary header in big archive.
Summary:
if the member file is XCOFF object file and has auxiliary header, the content of the member file need to be aligned at the
MAX(maximum alignment of .text , maximum alignment of .data). The "maximum alignment of .text" and "maximum alignment of .data" are two
field of auxiliary header of XCOFF object file.
Reviewers: James Henderson, Stephen Peckham
Differential Revision: https://reviews.llvm.org/D144872
Added:
llvm/test/tools/llvm-ar/big-archive-xcoff-align.test
Modified:
llvm/lib/Object/ArchiveWriter.cpp
llvm/test/Object/archive-malformed-object.test
Removed:
################################################################################
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index 19d2eff8b9fa9d..25b6eb90959352 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -331,6 +331,8 @@ struct MemberData {
std::string Header;
StringRef Data;
StringRef Padding;
+ uint64_t PreHeadPadSize = 0;
+ std::unique_ptr<SymbolicFile> SymFile = nullptr;
};
} // namespace
@@ -496,21 +498,66 @@ getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) {
}
}
-static Expected<bool> is64BitSymbolicFile(const StringRef &ObjStringRef) {
- MemoryBufferRef ObjMbf(ObjStringRef, "");
- // In the scenario when LLVMContext is populated SymbolicFile will contain a
- // reference to it, thus SymbolicFile should be destroyed first.
- LLVMContext Context;
- Expected<std::unique_ptr<SymbolicFile>> ObjOrErr =
- getSymbolicFile(ObjMbf, Context);
- if (!ObjOrErr)
- return ObjOrErr.takeError();
+static bool is64BitSymbolicFile(const SymbolicFile *SymObj) {
+ return SymObj != nullptr ? SymObj->is64Bit() : false;
+}
- // Treat non-symbolic file types as not 64-bits.
- if (!*ObjOrErr)
- return false;
+// Log2 of PAGESIZE(4096) on an AIX system.
+static const uint32_t Log2OfAIXPageSize = 12;
+
+// In the AIX big archive format, since the data content follows the member file
+// name, if the name ends on an odd byte, an extra byte will be added for
+// padding. This ensures that the data within the member file starts at an even
+// byte.
+static const uint32_t MinBigArchiveMemDataAlign = 2;
+
+template <typename AuxiliaryHeader>
+uint16_t getAuxMaxAlignment(uint16_t AuxHeaderSize, AuxiliaryHeader *AuxHeader,
+ uint16_t Log2OfMaxAlign) {
+ // If the member doesn't have an auxiliary header, it isn't a loadable object
+ // and so it just needs aligning at the minimum value.
+ if (AuxHeader == nullptr)
+ return MinBigArchiveMemDataAlign;
+
+ // If the auxiliary header does not have both MaxAlignOfData and
+ // MaxAlignOfText field, it is not a loadable shared object file, so align at
+ // the minimum value. The 'ModuleType' member is located right after
+ // 'MaxAlignOfData' in the AuxiliaryHeader.
+ if (AuxHeaderSize < offsetof(AuxiliaryHeader, ModuleType))
+ return MinBigArchiveMemDataAlign;
+
+ // If the XCOFF object file does not have a loader section, it is not
+ // loadable, so align at the minimum value.
+ if (AuxHeader->SecNumOfLoader == 0)
+ return MinBigArchiveMemDataAlign;
+
+ // The content of the loadable member file needs to be aligned at MAX(maximum
+ // alignment of .text, maximum alignment of .data) if there are both fields.
+ // If the desired alignment is > PAGESIZE, 32-bit members are aligned on a
+ // word boundary, while 64-bit members are aligned on a PAGESIZE(2^12=4096)
+ // boundary.
+ uint16_t Log2OfAlign =
+ std::max(AuxHeader->MaxAlignOfText, AuxHeader->MaxAlignOfData);
+ return 1 << (Log2OfAlign > Log2OfAIXPageSize ? Log2OfMaxAlign : Log2OfAlign);
+}
- return (*ObjOrErr)->is64Bit();
+// AIX big archives may contain shared object members. The AIX OS requires these
+// members to be aligned if they are 64-bit and recommends it for 32-bit
+// members. This ensures that when these members are loaded they are aligned in
+// memory.
+static uint32_t getMemberAlignment(SymbolicFile *SymObj) {
+ XCOFFObjectFile *XCOFFObj = dyn_cast_or_null<XCOFFObjectFile>(SymObj);
+ if (!XCOFFObj)
+ return MinBigArchiveMemDataAlign;
+
+ // If the desired alignment is > PAGESIZE, 32-bit members are aligned on a
+ // word boundary, while 64-bit members are aligned on a PAGESIZE boundary.
+ return XCOFFObj->is64Bit()
+ ? getAuxMaxAlignment(XCOFFObj->fileHeader64()->AuxHeaderSize,
+ XCOFFObj->auxiliaryHeader64(),
+ Log2OfAIXPageSize)
+ : getAuxMaxAlignment(XCOFFObj->fileHeader32()->AuxHeaderSize,
+ XCOFFObj->auxiliaryHeader32(), 2);
}
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
@@ -539,13 +586,8 @@ static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
uint64_t Pos = MembersOffset;
for (const MemberData &M : Members) {
if (isAIXBigArchive(Kind)) {
- Expected<bool> Is64BitOrErr = is64BitSymbolicFile(M.Data);
- // If there is an error, the error will have been emitted when
- // 'computeMemberData' called the 'getSymbol' function, so don't need to
- // handle it here.
- if (!Is64BitOrErr)
- cantFail(Is64BitOrErr.takeError());
- if (*Is64BitOrErr != Is64Bit) {
+ Pos += M.PreHeadPadSize;
+ if (is64BitSymbolicFile(M.SymFile.get()) != Is64Bit) {
Pos += M.Header.size() + M.Data.size() + M.Padding.size();
continue;
}
@@ -629,29 +671,19 @@ static bool isECObject(object::SymbolicFile &Obj) {
return false;
}
-static Expected<std::vector<unsigned>>
-getSymbols(MemoryBufferRef Buf, uint16_t Index, raw_ostream &SymNames,
- SymMap *SymMap, bool &HasObject) {
- // In the scenario when LLVMContext is populated SymbolicFile will contain a
- // reference to it, thus SymbolicFile should be destroyed first.
- LLVMContext Context;
-
+static Expected<std::vector<unsigned>> getSymbols(SymbolicFile *Obj,
+ uint16_t Index,
+ raw_ostream &SymNames,
+ SymMap *SymMap) {
std::vector<unsigned> Ret;
- Expected<std::unique_ptr<SymbolicFile>> ObjOrErr =
- getSymbolicFile(Buf, Context);
- if (!ObjOrErr)
- return ObjOrErr.takeError();
- // If the member is non-symbolic file, treat it as having no symbols.
- if (!*ObjOrErr)
+ if (Obj == nullptr)
return Ret;
- std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
-
std::map<std::string, uint16_t> *Map = nullptr;
if (SymMap)
Map = SymMap->UseECMap && isECObject(*Obj) ? &SymMap->ECMap : &SymMap->Map;
- HasObject = true;
+
for (const object::BasicSymbolRef &S : Obj->symbols()) {
if (!isArchiveSymbol(S))
continue;
@@ -681,9 +713,9 @@ static Expected<std::vector<MemberData>>
computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
object::Archive::Kind Kind, bool Thin, bool Deterministic,
SymtabWritingMode NeedSymbols, SymMap *SymMap,
- ArrayRef<NewArchiveMember> NewMembers) {
+ LLVMContext &Context, ArrayRef<NewArchiveMember> NewMembers) {
static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
-
+ uint64_t MemHeadPadSize = 0;
uint64_t Pos =
isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) : 0;
@@ -748,12 +780,16 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
// The big archive format needs to know the offset of the previous member
// header.
uint64_t PrevOffset = 0;
+ uint64_t NextMemHeadPadSize = 0;
+ std::unique_ptr<SymbolicFile> CurSymFile;
+ std::unique_ptr<SymbolicFile> NextSymFile;
uint16_t Index = 0;
- for (const NewArchiveMember &M : NewMembers) {
+
+ for (auto M = NewMembers.begin(); M < NewMembers.end(); ++M) {
std::string Header;
raw_string_ostream Out(Header);
- MemoryBufferRef Buf = M.Buf->getMemBufferRef();
+ MemoryBufferRef Buf = M->Buf->getMemBufferRef();
StringRef Data = Thin ? "" : Buf.getBuffer();
Index++;
@@ -771,26 +807,76 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
sys::TimePoint<std::chrono::seconds> ModTime;
if (UniqueTimestamps)
// Increment timestamp for each file of a given name.
- ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
+ ModTime = sys::toTimePoint(FilenameCount[M->MemberName]++);
else
- ModTime = M.ModTime;
+ ModTime = M->ModTime;
uint64_t Size = Buf.getBufferSize() + MemberPadding;
if (Size > object::Archive::MaxMemberSize) {
std::string StringMsg =
- "File " + M.MemberName.str() + " exceeds size limit";
+ "File " + M->MemberName.str() + " exceeds size limit";
return make_error<object::GenericBinaryError>(
std::move(StringMsg), object::object_error::parse_failed);
}
+ if (NeedSymbols != SymtabWritingMode::NoSymtab || isAIXBigArchive(Kind)) {
+ auto SetNextSymFile = [&NextSymFile,
+ &Context](MemoryBufferRef Buf,
+ StringRef MemberName) -> Error {
+ Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr =
+ getSymbolicFile(Buf, Context);
+ if (!SymFileOrErr)
+ return createFileError(MemberName, SymFileOrErr.takeError());
+ NextSymFile = std::move(*SymFileOrErr);
+ return Error::success();
+ };
+
+ if (M == NewMembers.begin())
+ if (Error Err = SetNextSymFile(Buf, M->MemberName))
+ return std::move(Err);
+
+ CurSymFile = std::move(NextSymFile);
+
+ if ((M + 1) != NewMembers.end())
+ if (Error Err = SetNextSymFile((M + 1)->Buf->getMemBufferRef(),
+ (M + 1)->MemberName))
+ return std::move(Err);
+ }
+
+ // In the big archive file format, we need to calculate and include the next
+ // member offset and previous member offset in the file member header.
if (isAIXBigArchive(Kind)) {
+ uint64_t OffsetToMemData = Pos + sizeof(object::BigArMemHdrType) +
+ alignTo(M->MemberName.size(), 2);
+
+ if (M == NewMembers.begin())
+ NextMemHeadPadSize =
+ alignToPowerOf2(OffsetToMemData,
+ getMemberAlignment(CurSymFile.get())) -
+ OffsetToMemData;
+
+ MemHeadPadSize = NextMemHeadPadSize;
+ Pos += MemHeadPadSize;
uint64_t NextOffset = Pos + sizeof(object::BigArMemHdrType) +
- alignTo(M.MemberName.size(), 2) + alignTo(Size, 2);
- printBigArchiveMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
- M.Perms, Size, PrevOffset, NextOffset);
+ alignTo(M->MemberName.size(), 2) + alignTo(Size, 2);
+
+ // If there is another member file after this, we need to calculate the
+ // padding before the header.
+ if ((M + 1) != NewMembers.end()) {
+ uint64_t OffsetToNextMemData = NextOffset +
+ sizeof(object::BigArMemHdrType) +
+ alignTo((M + 1)->MemberName.size(), 2);
+ NextMemHeadPadSize =
+ alignToPowerOf2(OffsetToNextMemData,
+ getMemberAlignment(NextSymFile.get())) -
+ OffsetToNextMemData;
+ NextOffset += NextMemHeadPadSize;
+ }
+ printBigArchiveMemberHeader(Out, M->MemberName, ModTime, M->UID, M->GID,
+ M->Perms, Size, PrevOffset, NextOffset);
PrevOffset = Pos;
} else {
- printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
+ printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, *M,
ModTime, Size);
}
Out.flush();
@@ -798,14 +884,17 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
std::vector<unsigned> Symbols;
if (NeedSymbols != SymtabWritingMode::NoSymtab) {
Expected<std::vector<unsigned>> SymbolsOrErr =
- getSymbols(Buf, Index, SymNames, SymMap, HasObject);
+ getSymbols(CurSymFile.get(), Index, SymNames, SymMap);
if (!SymbolsOrErr)
- return createFileError(M.MemberName, SymbolsOrErr.takeError());
+ return createFileError(M->MemberName, SymbolsOrErr.takeError());
Symbols = std::move(*SymbolsOrErr);
+ if (CurSymFile)
+ HasObject = true;
}
Pos += Header.size() + Data.size() + Padding.size();
- Ret.push_back({std::move(Symbols), std::move(Header), Data, Padding});
+ Ret.push_back({std::move(Symbols), std::move(Header), Data, Padding,
+ MemHeadPadSize, std::move(CurSymFile)});
}
// If there are no symbols, emit an empty symbol table, to satisfy Solaris
// tools, older versions of which expect a symbol table in a non-empty
@@ -876,10 +965,14 @@ static Error writeArchiveToStream(raw_ostream &Out,
if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe)
Kind = object::Archive::K_GNU;
+ // In the scenario when LLVMContext is populated SymbolicFile will contain a
+ // reference to it, thus SymbolicFile should be destroyed first.
+ LLVMContext Context;
+
SymMap.UseECMap = IsEC;
Expected<std::vector<MemberData>> DataOrErr = computeMemberData(
StringTable, SymNames, Kind, Thin, Deterministic, WriteSymtab,
- isCOFFArchive(Kind) ? &SymMap : nullptr, NewMembers);
+ isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers);
if (Error E = DataOrErr.takeError())
return E;
std::vector<MemberData> &Data = *DataOrErr;
@@ -902,6 +995,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
for (const auto &M : Data) {
// Record the start of the member's offset
+ LastMemberEndOffset += M.PreHeadPadSize;
LastMemberHeaderOffset = LastMemberEndOffset;
// Account for the size of each part associated with the member.
LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size();
@@ -913,13 +1007,9 @@ static Error writeArchiveToStream(raw_ostream &Out,
// members. As a big archive can have both 32-bit and 64-bit file members,
// we need to know the number of symbols in each symbol table individually.
if (isAIXBigArchive(Kind) && ShouldWriteSymtab) {
- Expected<bool> Is64BitOrErr = is64BitSymbolicFile(M.Data);
- if (Error E = Is64BitOrErr.takeError())
- return E;
-
- if (!*Is64BitOrErr)
- NumSyms32 += M.Symbols.size();
- }
+ if (!is64BitSymbolicFile(M.SymFile.get()))
+ NumSyms32 += M.Symbols.size();
+ }
}
std::optional<uint64_t> HeadersSize;
@@ -1000,13 +1090,14 @@ static Error writeArchiveToStream(raw_ostream &Out,
for (size_t I = 0, Size = NewMembers.size(); I != Size; ++I) {
const NewArchiveMember &Member = NewMembers[I];
MemberTableNameStrTblSize += Member.MemberName.size() + 1;
+ MemberEndOffset += Data[I].PreHeadPadSize;
MemberOffsets.push_back(MemberEndOffset);
MemberNames.push_back(Member.MemberName);
// File member name ended with "`\n". The length is included in
// BigArMemHdrType.
MemberEndOffset += sizeof(object::BigArMemHdrType) +
- alignTo(Data[I].Data.size(), 2) +
- alignTo(Member.MemberName.size(), 2);
+ alignTo(Data[I].Data.size(), 2) +
+ alignTo(Member.MemberName.size(), 2);
}
// AIX member table size.
@@ -1021,16 +1112,11 @@ static Error writeArchiveToStream(raw_ostream &Out,
if (ShouldWriteSymtab && NumSyms)
// Generate the symbol names for the members.
- for (const NewArchiveMember &M : NewMembers) {
- MemoryBufferRef Buf = M.Buf->getMemBufferRef();
- Expected<bool> Is64BitOrErr = is64BitSymbolicFile(Buf.getBuffer());
- if (!Is64BitOrErr)
- return Is64BitOrErr.takeError();
-
- bool HasObject;
- Expected<std::vector<unsigned>> SymbolsOrErr =
- getSymbols(Buf, 0, *Is64BitOrErr ? SymNames64 : SymNames32, nullptr,
- HasObject);
+ for (const auto &M : Data) {
+ Expected<std::vector<unsigned>> SymbolsOrErr = getSymbols(
+ M.SymFile.get(), 0,
+ is64BitSymbolicFile(M.SymFile.get()) ? SymNames64 : SymNames32,
+ nullptr);
if (!SymbolsOrErr)
return SymbolsOrErr.takeError();
}
@@ -1069,9 +1155,12 @@ static Error writeArchiveToStream(raw_ostream &Out,
// symbol table.
printWithSpacePadding(Out, GlobalSymbolOffset, 20);
printWithSpacePadding(Out, GlobalSymbolOffset64, 20);
- printWithSpacePadding(
- Out, NewMembers.size() ? sizeof(object::BigArchive::FixLenHdr) : 0,
- 20); // Offset to first archive member
+ printWithSpacePadding(Out,
+ NewMembers.size()
+ ? sizeof(object::BigArchive::FixLenHdr) +
+ Data[0].PreHeadPadSize
+ : 0,
+ 20); // Offset to first archive member
printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0,
20); // Offset to last archive member
printWithSpacePadding(
@@ -1079,6 +1168,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
20); // Offset to first member of free list - Not supported yet
for (const MemberData &M : Data) {
+ Out << std::string(M.PreHeadPadSize, '\0');
Out << M.Header << M.Data;
if (M.Data.size() % 2)
Out << '\0';
diff --git a/llvm/test/Object/archive-malformed-object.test b/llvm/test/Object/archive-malformed-object.test
index b254dcbd029e21..a92762975bda6d 100644
--- a/llvm/test/Object/archive-malformed-object.test
+++ b/llvm/test/Object/archive-malformed-object.test
@@ -5,11 +5,22 @@
# RUN: split-file %s %t.dir
# RUN: cd %t.dir
-## Malformed bitcode object.
+## Malformed bitcode object is the first file member of archive if the symbol table is required.
# RUN: llvm-as input.ll -o input.bc
+# RUN: cp input.bc good.bc
# RUN: %python -c "with open('input.bc', 'a') as f: f.truncate(10)"
# RUN: not llvm-ar rc bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+## Malformed bitcode object is the last file member of archive if the symbol table is required.
+# RUN: rm -rf bad.a
+# RUN: not llvm-ar rc bad.a good.bc input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+
+## Malformed bitcode object if the symbol table is not required for big archive.
+# RUN: rm -rf bad.a
+# RUN: not llvm-ar --format=bigarchive rcS bad.a input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+# RUN: rm -rf bad.a
+# RUN: not llvm-ar --format=bigarchive rcS bad.a good.bc input.bc 2>&1 | FileCheck %s --check-prefix=ERR1
+
# ERR1: error: bad.a: 'input.bc': Invalid bitcode signature
## Non-bitcode malformed file.
@@ -18,8 +29,8 @@
# ERR2: error: bad.a: 'input.o': section header table goes past the end of the file: e_shoff = 0x9999
-## Don't emit an error if the symbol table is not required.
-# RUN: llvm-ar rcS good.a input.o input.bc
+## Don't emit an error if the symbol table is not required for formats other than the big archive format.
+# RUN: llvm-ar --format=gnu rcS good.a input.o input.bc
# RUN: llvm-ar t good.a | FileCheck %s --check-prefix=CONTENTS
# CONTENTS: input.o
diff --git a/llvm/test/tools/llvm-ar/big-archive-xcoff-align.test b/llvm/test/tools/llvm-ar/big-archive-xcoff-align.test
new file mode 100644
index 00000000000000..8682ebf85b1f71
--- /dev/null
+++ b/llvm/test/tools/llvm-ar/big-archive-xcoff-align.test
@@ -0,0 +1,109 @@
+## Test the alignment of XCOFF object files in the big archive format.
+
+# RUN: rm -rf %t && mkdir %t
+# RUN: cd %t
+
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1DF -DSECNAME=.data %s -o t32_1.o
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1F7 -DSECNAME=.data %s -o t64_1.o
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1DF -DSECNAME=.text %s -o t32_2.o
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1F7 -DSECNAME=.text %s -o t64_2.o
+# RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o t32_nomaxdata_text.o
+# RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o t64_nomaxdata_text.o
+# RUN: yaml2obj --docnum=3 -DFLAG=0x1DF %s -o t32_maxdata_text.o
+# RUN: yaml2obj --docnum=3 -DFLAG=0x1F7 %s -o t64_maxdata_text.o
+# RUN: yaml2obj --docnum=4 -DFLAG=0x1DF %s -o t32_noloader.o
+# RUN: yaml2obj --docnum=4 -DFLAG=0x1F7 %s -o t64_noloader.o
+# RUN: yaml2obj --docnum=5 -DFLAG=0x1DF %s -o t32_excess.o
+# RUN: yaml2obj --docnum=5 -DFLAG=0x1F7 %s -o t64_excess.o
+
+# RUN: echo -e "import sys\nf=open(sys.argv[1],\"rb\");f.seek(int(sys.argv[2]));print(f.read(2));f.close()" > print_magic.py
+
+## Test that the content of an XCOFF object file, which has an auxiliary header,
+## is aligned in a big archive based on the content of auxiliary header.
+# RUN: env OBJECT_MODE=32_64 llvm-ar -q t_aux.a t32_nomaxdata_text.o t64_nomaxdata_text.o t32_maxdata_text.o t64_maxdata_text.o t32_noloader.o t64_noloader.o t32_excess.o t64_excess.o
+## The content of t32_nomaxdata_text, t64_nomaxdata_text.o aligned at 2.
+# RUN: %python print_magic.py t_aux.a 262 | FileCheck --check-prefix=MAGIC32 %s
+# RUN: %python print_magic.py t_aux.a 528 | FileCheck --check-prefix=MAGIC64 %s
+## The content of t32_maxdata_text.o, t64_maxdata_text.o aligned at 2^8.
+# RUN: %python print_magic.py t_aux.a 1024 | FileCheck --check-prefix=MAGIC32 %s
+# RUN: %python print_magic.py t_aux.a 1536 | FileCheck --check-prefix=MAGIC64 %s
+## The content of t32_noloader.o, t64_noloader.o aligned at 2.
+# RUN: %python print_magic.py t_aux.a 1870 | FileCheck --check-prefix=MAGIC32 %s
+# RUN: %python print_magic.py t_aux.a 2130 | FileCheck --check-prefix=MAGIC64 %s
+## The content of t32_excess.o aligned at word.
+# RUN: %python print_magic.py t_aux.a 2464 | FileCheck --check-prefix=MAGIC32 %s
+## The content of t64_excess.o aligned at 2^12.
+# RUN: %python print_magic.py t_aux.a 4096 | FileCheck --check-prefix=MAGIC64 %s
+
+## Test that the content of an XCOFF object file, which does not have an auxiliary
+## header, is aligned at 2 in a big archive.
+# RUN: env OBJECT_MODE=32_64 llvm-ar -q t3.a t32_1.o t64_1.o t32_2.o t64_2.o
+# # RUN: %python print_magic.py t3.a 250 | FileCheck --check-prefix=MAGIC32 %s
+# # RUN: %python print_magic.py t3.a 432 | FileCheck -check-prefix=MAGIC64 %s
+# # RUN: %python print_magic.py t3.a 650 | FileCheck --check-prefix=MAGIC32 %s
+# # RUN: %python print_magic.py t3.a 832 | FileCheck -check-prefix=MAGIC64 %s
+
+# MAGIC64: b'\x01\xf7'
+# MAGIC32: b'\x01\xdf'
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: [[FLAG]]
+Sections:
+ - Name: [[SECNAME]]
+ Flags: [ STYP_DATA ]
+
+## The auxiliary header has neither the MaxAlignOfData nor MaxAlignOfText field.
+--- !XCOFF
+FileHeader:
+ MagicNumber: [[FLAG]]
+ AuxiliaryHeaderSize: 12
+AuxiliaryHeader:
+ Magic: 0x10B
+ SecNumOfLoader: 1
+Sections:
+ - Name: .text
+ Flags: [ STYP_DATA ]
+
+## The auxiliary header has both MaxAlignOfData and MaxAlignOfText fields.
+--- !XCOFF
+FileHeader:
+ MagicNumber: [[FLAG]]
+ AuxiliaryHeaderSize: 48
+AuxiliaryHeader:
+ Magic: 0x10B
+ SecNumOfLoader: 1
+ MaxAlignOfText: 6
+ MaxAlignOfData: 8
+Sections:
+ - Name: .text
+ Flags: [ STYP_DATA ]
+
+## The auxiliary header does not have a loader section.
+--- !XCOFF
+FileHeader:
+ MagicNumber: [[FLAG]]
+ AuxiliaryHeaderSize: 34
+AuxiliaryHeader:
+ Magic: 0x10B
+ SecNumOfLoader: 0
+ MaxAlignOfText: 14
+ MaxAlignOfData: 8
+Sections:
+ - Name: .text
+ Flags: [ STYP_DATA ]
+
+## The auxiliary header has both MaxAlignOfData and MaxAlignOfText fields
+## but max(MaxAlignOfData, MaxAlignOfText) exceeds the page size(2^12).
+--- !XCOFF
+FileHeader:
+ MagicNumber: [[FLAG]]
+ AuxiliaryHeaderSize: 48
+AuxiliaryHeader:
+ Magic: 0x10B
+ SecNumOfLoader: 1
+ MaxAlignOfText: 14
+ MaxAlignOfData: 8
+Sections:
+ - Name: .text
+ Flags: [ STYP_DATA ]
More information about the llvm-commits
mailing list