[llvm] [llvm-objcopy][ELF] Add an option to remove notes (PR #118739)
Igor Kudrin via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 23 13:00:00 PST 2024
https://github.com/igorkudrin updated https://github.com/llvm/llvm-project/pull/118739
>From 24308b26df6af7c9e027db9ef637a8da75fdf93f Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Wed, 27 Nov 2024 22:31:05 -0800
Subject: [PATCH 01/11] [llvm-objcopy][ELF] Add an option to remove notes
This adds an option `--remove-note` to selectively delete notes in an
ELF file. For now, it is expected to be useful for editing core dump
files; in particular, it searches for the notes in `PT_NOTE` segments
and does not handle nested segments. The implementation can be extended
later as needed.
---
llvm/include/llvm/ObjCopy/ELF/ELFConfig.h | 9 ++
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 96 ++++++++++++++++++
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 21 ++++
llvm/lib/ObjCopy/ELF/ELFObject.h | 5 +
.../tools/llvm-objcopy/ELF/remove-note.test | 98 +++++++++++++++++++
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 39 ++++++++
llvm/tools/llvm-objcopy/ObjcopyOpts.td | 4 +
7 files changed, 272 insertions(+)
create mode 100644 llvm/test/tools/llvm-objcopy/ELF/remove-note.test
diff --git a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
index 59960b65307430..01a8762cfb9c37 100644
--- a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
+++ b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
@@ -15,6 +15,12 @@
namespace llvm {
namespace objcopy {
+// Note to remove info specified by --remove-note option.
+struct RemoveNoteInfo {
+ StringRef Name;
+ uint32_t TypeId;
+};
+
// ELF specific configuration for copying/stripping a single file.
struct ELFConfig {
uint8_t NewSymbolVisibility = (uint8_t)ELF::STV_DEFAULT;
@@ -31,6 +37,9 @@ struct ELFConfig {
bool KeepFileSymbols = false;
bool LocalizeHidden = false;
bool VerifyNoteSections = true;
+
+ // Notes specified by --remove-note option.
+ SmallVector<RemoveNoteInfo, 0> NotesToRemove;
};
} // namespace objcopy
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 4793651f1d4e0b..1df64b0b7ce886 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -609,6 +609,97 @@ static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,
Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
}
+template <class ELFT>
+static Error removeNoteImpl(Object &Obj,
+ ArrayRef<RemoveNoteInfo> NotesToRemove) {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT);
+ for (Segment &Seg : Obj.segments()) {
+ // TODO: Support nested segments
+ if (Seg.Type != PT_NOTE || Seg.ParentSegment)
+ continue;
+
+ // Find chunks of the segment data to remove
+ struct DeletedRange {
+ uint64_t OldFrom;
+ uint64_t OldTo;
+ uint64_t NewOffset;
+ };
+ std::vector<DeletedRange> DataToRemove;
+ ArrayRef<uint8_t> OldData = Seg.getContents();
+ size_t Align = std::max<size_t>(4, Seg.Align);
+ uint64_t Offset = 0;
+ while (Offset + sizeof(Elf_Nhdr) <= OldData.size()) {
+ auto Nhdr = reinterpret_cast<const Elf_Nhdr *>(OldData.data() + Offset);
+ size_t FullSize = Nhdr->getSize(Align);
+ if (Offset + FullSize > OldData.size())
+ break;
+ Elf_Note Note(*Nhdr);
+ if (llvm::any_of(NotesToRemove, [&](const RemoveNoteInfo &NoteInfo) {
+ return NoteInfo.TypeId == Note.getType() &&
+ (NoteInfo.Name.empty() || NoteInfo.Name == Note.getName());
+ }))
+ DataToRemove.push_back({Offset, Offset + FullSize, 0});
+ Offset += FullSize;
+ }
+ if (DataToRemove.empty())
+ continue;
+
+ // Prepare the new segment data
+ std::vector<uint8_t> NewData;
+ NewData.reserve(OldData.size());
+ Offset = 0;
+ for (auto &RemRange : DataToRemove) {
+ if (Offset < RemRange.OldFrom) {
+ auto Slice = OldData.slice(Offset, RemRange.OldFrom - Offset);
+ NewData.insert(NewData.end(), Slice.begin(), Slice.end());
+ }
+ RemRange.NewOffset = NewData.size();
+ Offset = RemRange.OldTo;
+ }
+ if (Offset < OldData.size()) {
+ auto Slice = OldData.slice(Offset);
+ NewData.insert(NewData.end(), Slice.begin(), Slice.end());
+ }
+
+ auto CalculateNewOffset = [&](uint64_t SecOffset) {
+ uint64_t Offset = SecOffset - Seg.Offset;
+ auto It =
+ llvm::upper_bound(DataToRemove, Offset,
+ [](const uint64_t &Off, const DeletedRange &Range) {
+ return Off < Range.OldFrom;
+ });
+ if (It != DataToRemove.begin()) {
+ --It;
+ Offset = (Offset > It->OldTo) ? (Offset - It->OldTo + It->NewOffset)
+ : It->NewOffset;
+ }
+ return Offset + Seg.Offset;
+ };
+
+ // Remap the segment's sections
+ DenseMap<const SectionBase *, std::pair<uint64_t, uint64_t>> Mapping;
+ for (const SectionBase *Sec : Seg.Sections) {
+ uint64_t NewOffset = CalculateNewOffset(Sec->Offset);
+ uint64_t NewSize =
+ CalculateNewOffset(Sec->Offset + Sec->Size) - NewOffset;
+ Mapping.try_emplace(Sec, NewOffset, NewSize);
+ }
+
+ Obj.updateSegmentData(Seg, std::move(NewData), Mapping);
+ }
+ return Error::success();
+}
+
+static Error removeNote(Object &Obj, endianness Endianness,
+ ArrayRef<RemoveNoteInfo> NotesToRemove) {
+ // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
+ // header, so the parsers are the same.
+ if (Endianness == endianness::little)
+ return removeNoteImpl<ELF64LE>(Obj, NotesToRemove);
+ else
+ return removeNoteImpl<ELF64BE>(Obj, NotesToRemove);
+}
+
static Error
handleUserSection(const NewSectionInfo &NewSection,
function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) {
@@ -799,6 +890,11 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
? endianness::little
: endianness::big;
+ if (!ELFConfig.NotesToRemove.empty()) {
+ if (Error Err = removeNote(Obj, E, ELFConfig.NotesToRemove))
+ return Err;
+ }
+
for (const NewSectionInfo &AddedSection : Config.AddSection) {
auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) -> Error {
OwnedDataSection &NewSection =
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 01c2f24629077a..9f460f685706c8 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2308,6 +2308,27 @@ Error Object::addNewSymbolTable() {
return Error::success();
}
+void Object::updateSegmentData(
+ Segment &S, std::vector<uint8_t> NewSegmentData,
+ const DenseMap<const SectionBase *, std::pair<uint64_t, uint64_t>>
+ &SectionMapping) {
+ auto It =
+ UpdatedSegments.insert_or_assign(&S, std::move(NewSegmentData)).first;
+ S.Contents = It->second;
+ S.FileSize = S.Contents.size();
+ if (S.MemSize)
+ S.MemSize = S.FileSize;
+ assert(SectionMapping.size() == S.Sections.size());
+ for (const auto &SM : SectionMapping) {
+ assert(SM.first->ParentSegment == &S && S.Sections.count(SM.first));
+ assert(SM.second.first >= S.Offset);
+ assert((SM.second.first + SM.second.second) <= (S.Offset + S.FileSize));
+ SectionBase *MutSec = const_cast<SectionBase *>(SM.first);
+ MutSec->Offset = SM.second.first;
+ MutSec->Size = SM.second.second;
+ }
+}
+
// Orders segments such that if x = y->ParentSegment then y comes before x.
static void orderSegments(std::vector<Segment *> &Segments) {
llvm::stable_sort(Segments, compareSegmentsByOffset);
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 6ccf85387131e4..5e16d4c0c1885a 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -1159,6 +1159,7 @@ class Object {
std::vector<SegPtr> Segments;
std::vector<SecPtr> RemovedSections;
DenseMap<SectionBase *, std::vector<uint8_t>> UpdatedSections;
+ DenseMap<Segment *, std::vector<uint8_t>> UpdatedSegments;
static bool sectionIsAlloc(const SectionBase &Sec) {
return Sec.Flags & ELF::SHF_ALLOC;
@@ -1234,6 +1235,10 @@ class Object {
Segments.emplace_back(std::make_unique<Segment>(Data));
return *Segments.back();
}
+ void updateSegmentData(
+ Segment &S, std::vector<uint8_t> NewSegmentData,
+ const DenseMap<const SectionBase *, std::pair<uint64_t, uint64_t>>
+ &SectionMapping);
bool isRelocatable() const {
return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
}
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
new file mode 100644
index 00000000000000..b24538e26d019e
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -0,0 +1,98 @@
+# RUN: not llvm-objcopy --remove-note= - 2>&1 | FileCheck %s --check-prefix=ERR-NOTYPEID
+# RUN: not llvm-objcopy --remove-note=/1 - 2>&1 | FileCheck %s --check-prefix=ERR-EMPTYNAME
+# RUN: not llvm-objcopy --remove-note=CORE/1/2 - 2>&1 | FileCheck %s --check-prefix=ERR-INVNUM1
+# RUN: not llvm-objcopy --remove-note=Notanumber - 2>&1 | FileCheck %s --check-prefix=ERR-INVNUM2
+# RUN: not llvm-objcopy --remove-note=CORE/Notanumber - 2>&1 | FileCheck %s --check-prefix=ERR-INVNUM2
+
+# ERR-NOTYPEID: error: bad format for --remove-note, missing type_id
+# ERR-EMPTYNAME: error: bad format for --remove-note, note name is empty
+# ERR-INVNUM1: error: bad note type_id for --remove-note: '1/2'
+# ERR-INVNUM2: error: bad note type_id for --remove-note: 'Notanumber'
+
+# RUN: yaml2obj -D ALIGN=8 %s -o - \
+# RUN: | llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/0x03 - - \
+# RUN: | llvm-readobj --segments --sections --notes - \
+# RUN: | FileCheck %s -D#SIZE=64
+
+# RUN: yaml2obj -D ALIGN=4 %s -o - \
+# RUN: | llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/0x03 - - \
+# RUN: | llvm-readobj --segments --sections --notes - \
+# RUN: | FileCheck %s -D#SIZE=48
+
+# CHECK: Sections [
+# CHECK: Section {
+# CHECK: Name: .note
+# CHECK-NEXT: Type: SHT_NOTE
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset: [[OFFSET:0x.+]]
+# CHECK-NEXT: Size: [[#%d,SIZE]]
+
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_NOTE
+# CHECK-NEXT: Offset: [[OFFSET]]
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: [[#%d,SIZE]]
+# CHECK-NEXT: MemSize: 0
+
+# CHECK: NoteSections [
+# CHECK-NEXT: NoteSection {
+# CHECK-NEXT: Name:
+# CHECK-NEXT: Offset: [[OFFSET]]
+# CHECK-NEXT: Size: 0x[[#%x,SIZE]]
+# CHECK-NEXT: Notes [
+# CHECK-NEXT: {
+# CHECK-NEXT: Owner: CORE
+# CHECK-NEXT: Data size: 0x2
+# CHECK-NEXT: Type: NT_FPREGSET
+# CHECK-NEXT: Description data (
+# CHECK-NEXT: 0000: 0202
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: {
+# CHECK-NEXT: Owner: CORE
+# CHECK-NEXT: Data size: 0x2
+# CHECK-NEXT: Type: NT_TASKSTRUCT
+# CHECK-NEXT: Description data (
+# CHECK-NEXT: 0000: 0404
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_CORE
+ Machine: EM_X86_64
+ProgramHeaders:
+ - Type: PT_NOTE
+ MemSize: 0
+ FirstSec: .note
+ LastSec: .note
+Sections:
+ - Name: .note
+ Type: SHT_NOTE
+ AddressAlign: [[ALIGN]]
+ Notes:
+ - Name: CORE
+ Type: 0x01
+ Desc: 0101
+ - Name: CORE
+ Type: 0x02
+ Desc: 0202
+ - Name: CORE
+ Type: 0x03
+ Desc: 0303
+ - Name: CORE
+ Type: 0x04
+ Desc: 0404
+ - Name: LINUX
+ Type: 0x01
+ Desc: 0505
+...
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 104d802b1e1eeb..5e348d65adca18 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -527,6 +527,37 @@ static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
return SI;
}
+static Expected<RemoveNoteInfo> parseRemoveNoteInfo(StringRef FlagValue) {
+ // Parse value given with --remove-note option. The format is:
+ //
+ // [name/]type_id
+ //
+ // where:
+ // <name> - optional note name. If not given, all notes with the specified
+ // <type_id> are removed.
+ // <type_id> - note type value, can be decimal or hexadecimal number prefixed
+ // with 0x.
+ RemoveNoteInfo NI;
+ if (FlagValue.empty())
+ return createStringError(errc::invalid_argument,
+ "bad format for --remove-note, missing type_id");
+ SmallVector<StringRef, 2> Tokens;
+ FlagValue.split(Tokens, '/', /*MaxSplit=*/1);
+ assert(!Tokens.empty() && Tokens.size() <= 2);
+ if (Tokens.size() == 2) {
+ if (Tokens[0].empty())
+ return createStringError(
+ errc::invalid_argument,
+ "bad format for --remove-note, note name is empty");
+ NI.Name = Tokens[0];
+ }
+ if (Tokens.back().getAsInteger(0, NI.TypeId))
+ return createStringError(errc::invalid_argument,
+ "bad note type_id for --remove-note: '%s'",
+ Tokens.back().str().c_str());
+ return NI;
+}
+
// Parse input option \p ArgValue and load section data. This function
// extracts section name and name of the file keeping section data from
// ArgValue, loads data from the file, and stores section name and data
@@ -1210,6 +1241,14 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
};
}
+ for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_note)) {
+ Expected<RemoveNoteInfo> NoteInfo = parseRemoveNoteInfo(Arg->getValue());
+ if (!NoteInfo)
+ return NoteInfo.takeError();
+
+ ELFConfig.NotesToRemove.push_back(*NoteInfo);
+ }
+
if (Config.DecompressDebugSections &&
Config.CompressionType != DebugCompressionType::None) {
return createStringError(
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index 434b5ff92324eb..fbc6a59d9461e7 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -297,3 +297,7 @@ defm pad_to
"of zero or the value specified by the --gap-fill option. "
"This option is only supported for ELF input and binary output">,
MetaVarName<"address">;
+
+defm remove_note
+ : Eq<"remove-note", "Remove note(s) with <type_id> and optional <name>">,
+ MetaVarName<"[name/]type_id">;
>From 3550f3afd72092e1664b3c3d46b8f1a5fce7c5a3 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 13 Dec 2024 22:35:09 -0800
Subject: [PATCH 02/11] fixup: update parsing the argument
---
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 23 +++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index bfd67c558074ef..a5643f0bec5d92 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -549,23 +549,24 @@ static Expected<RemoveNoteInfo> parseRemoveNoteInfo(StringRef FlagValue) {
// <type_id> - note type value, can be decimal or hexadecimal number prefixed
// with 0x.
RemoveNoteInfo NI;
- if (FlagValue.empty())
- return createStringError(errc::invalid_argument,
- "bad format for --remove-note, missing type_id");
- SmallVector<StringRef, 2> Tokens;
- FlagValue.split(Tokens, '/', /*MaxSplit=*/1);
- assert(!Tokens.empty() && Tokens.size() <= 2);
- if (Tokens.size() == 2) {
- if (Tokens[0].empty())
+ StringRef TypeIdStr;
+ if (auto Idx = FlagValue.find('/'); Idx != StringRef::npos) {
+ if (Idx == 0)
return createStringError(
errc::invalid_argument,
"bad format for --remove-note, note name is empty");
- NI.Name = Tokens[0];
+ NI.Name = FlagValue.slice(0, Idx);
+ TypeIdStr = FlagValue.substr(Idx + 1);
+ } else {
+ TypeIdStr = FlagValue;
}
- if (Tokens.back().getAsInteger(0, NI.TypeId))
+ if (TypeIdStr.empty())
+ return createStringError(errc::invalid_argument,
+ "bad format for --remove-note, missing type_id");
+ if (TypeIdStr.getAsInteger(0, NI.TypeId))
return createStringError(errc::invalid_argument,
"bad note type_id for --remove-note: '%s'",
- Tokens.back().str().c_str());
+ TypeIdStr.str().c_str());
return NI;
}
>From 51b05f292ac7475722eedb3f9e1e11040e608dc0 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 13 Dec 2024 22:35:34 -0800
Subject: [PATCH 03/11] fixup: update tests
---
llvm/test/tools/llvm-objcopy/ELF/remove-note.test | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
index b24538e26d019e..258ec06fba321e 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -1,4 +1,5 @@
# RUN: not llvm-objcopy --remove-note= - 2>&1 | FileCheck %s --check-prefix=ERR-NOTYPEID
+# RUN: not llvm-objcopy --remove-note=CORE/ - 2>&1 | FileCheck %s --check-prefix=ERR-NOTYPEID
# RUN: not llvm-objcopy --remove-note=/1 - 2>&1 | FileCheck %s --check-prefix=ERR-EMPTYNAME
# RUN: not llvm-objcopy --remove-note=CORE/1/2 - 2>&1 | FileCheck %s --check-prefix=ERR-INVNUM1
# RUN: not llvm-objcopy --remove-note=Notanumber - 2>&1 | FileCheck %s --check-prefix=ERR-INVNUM2
@@ -9,15 +10,13 @@
# ERR-INVNUM1: error: bad note type_id for --remove-note: '1/2'
# ERR-INVNUM2: error: bad note type_id for --remove-note: 'Notanumber'
-# RUN: yaml2obj -D ALIGN=8 %s -o - \
-# RUN: | llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/0x03 - - \
-# RUN: | llvm-readobj --segments --sections --notes - \
-# RUN: | FileCheck %s -D#SIZE=64
+# RUN: yaml2obj -D ALIGN=8 %s -o %t8
+# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/2 --remove-note=CORE/0x03 %t8 %t8o
+# RUN: llvm-readobj --segments --sections --notes %t8o | FileCheck %s -D#SIZE=64
-# RUN: yaml2obj -D ALIGN=4 %s -o - \
-# RUN: | llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/0x03 - - \
-# RUN: | llvm-readobj --segments --sections --notes - \
-# RUN: | FileCheck %s -D#SIZE=48
+# RUN: yaml2obj -D ALIGN=4 %s -o %t4
+# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4 %t4o
+# RUN: llvm-readobj --segments --sections --notes %t4o | FileCheck %s -D#SIZE=48
# CHECK: Sections [
# CHECK: Section {
>From 1bad501c0095b9f4656766f6849848268495a06e Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 13 Dec 2024 22:48:40 -0800
Subject: [PATCH 04/11] fixup: add the option to the command guide
---
llvm/docs/CommandGuide/llvm-objcopy.rst | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index e6af47ce9710a6..c57d367261a121 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -464,6 +464,11 @@ them.
Preserve access and modification timestamps in the output.
+.. option:: --remove-note [<name>/]<type>
+
+ Remove notes of integer type ``<type>`` and name ``<name>`` from SHT_NOTE
+ sections and PT_NOTE segments. Can be specified multiple times.
+
.. option:: --rename-section <old>=<new>[,<flag>,...]
Rename sections called ``<old>`` to ``<new>`` in the output, and apply any
>From 3b17fdb705a4ae7ab622bb1c85a13f7821f5570f Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Thu, 19 Dec 2024 18:34:46 -0800
Subject: [PATCH 05/11] fixup: fix updating offsets
---
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 9 +++-
.../tools/llvm-objcopy/ELF/remove-note.test | 46 ++++++++++++++-----
2 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 9f460f685706c8..5f2cef8ac86046 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2312,6 +2312,11 @@ void Object::updateSegmentData(
Segment &S, std::vector<uint8_t> NewSegmentData,
const DenseMap<const SectionBase *, std::pair<uint64_t, uint64_t>>
&SectionMapping) {
+ // TODO: Update the parent segment
+ assert(!S.ParentSegment);
+ // TODO: Update nested segments
+ assert(!llvm::any_of(
+ Segments, [&S](const SegPtr &Seg) { return Seg->ParentSegment == &S; }));
auto It =
UpdatedSegments.insert_or_assign(&S, std::move(NewSegmentData)).first;
S.Contents = It->second;
@@ -2319,12 +2324,14 @@ void Object::updateSegmentData(
if (S.MemSize)
S.MemSize = S.FileSize;
assert(SectionMapping.size() == S.Sections.size());
+ assert(S.Offset == S.OriginalOffset);
for (const auto &SM : SectionMapping) {
assert(SM.first->ParentSegment == &S && S.Sections.count(SM.first));
assert(SM.second.first >= S.Offset);
assert((SM.second.first + SM.second.second) <= (S.Offset + S.FileSize));
+ assert(SM.first->Offset == SM.first->OriginalOffset);
SectionBase *MutSec = const_cast<SectionBase *>(SM.first);
- MutSec->Offset = SM.second.first;
+ MutSec->OriginalOffset = MutSec->Offset = SM.second.first;
MutSec->Size = SM.second.second;
}
}
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
index 258ec06fba321e..8475e3f8c31737 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -12,36 +12,50 @@
# RUN: yaml2obj -D ALIGN=8 %s -o %t8
# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/2 --remove-note=CORE/0x03 %t8 %t8o
-# RUN: llvm-readobj --segments --sections --notes %t8o | FileCheck %s -D#SIZE=64
+# RUN: llvm-readobj --segments --sections --notes %t8o | FileCheck %s -D#SIZE0=32 -D#SIZE1=32
# RUN: yaml2obj -D ALIGN=4 %s -o %t4
# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4 %t4o
-# RUN: llvm-readobj --segments --sections --notes %t4o | FileCheck %s -D#SIZE=48
+# RUN: llvm-readobj --segments --sections --notes %t4o | FileCheck %s -D#SIZE0=24 -D#SIZE1=24
# CHECK: Sections [
# CHECK: Section {
-# CHECK: Name: .note
+# CHECK: Name: .note0
# CHECK-NEXT: Type: SHT_NOTE
# CHECK-NEXT: Flags [
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
-# CHECK-NEXT: Offset: [[OFFSET:0x.+]]
-# CHECK-NEXT: Size: [[#%d,SIZE]]
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0:]]
+# CHECK-NEXT: Size: [[#%d,SIZE0]]
+# CHECK: Name: .note1
+# CHECK-NEXT: Type: SHT_NOTE
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0]]
+# CHECK-NEXT: Size: [[#%d,SIZE1]]
+# CHECK: Name: .note2
+# CHECK-NEXT: Type: SHT_NOTE
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0+SIZE1]]
+# CHECK-NEXT: Size: 0
# CHECK: ProgramHeaders [
# CHECK-NEXT: ProgramHeader {
# CHECK-NEXT: Type: PT_NOTE
-# CHECK-NEXT: Offset: [[OFFSET]]
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0]]
# CHECK-NEXT: VirtualAddress: 0x0
# CHECK-NEXT: PhysicalAddress: 0x0
-# CHECK-NEXT: FileSize: [[#%d,SIZE]]
+# CHECK-NEXT: FileSize: [[#%d,SIZE0+SIZE1]]
# CHECK-NEXT: MemSize: 0
# CHECK: NoteSections [
# CHECK-NEXT: NoteSection {
# CHECK-NEXT: Name:
-# CHECK-NEXT: Offset: [[OFFSET]]
-# CHECK-NEXT: Size: 0x[[#%x,SIZE]]
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0]]
+# CHECK-NEXT: Size: 0x[[#%X,SIZE0+SIZE1]]
# CHECK-NEXT: Notes [
# CHECK-NEXT: {
# CHECK-NEXT: Owner: CORE
@@ -72,10 +86,10 @@ FileHeader:
ProgramHeaders:
- Type: PT_NOTE
MemSize: 0
- FirstSec: .note
- LastSec: .note
+ FirstSec: .note0
+ LastSec: .note2
Sections:
- - Name: .note
+ - Name: .note0
Type: SHT_NOTE
AddressAlign: [[ALIGN]]
Notes:
@@ -85,12 +99,20 @@ Sections:
- Name: CORE
Type: 0x02
Desc: 0202
+ - Name: .note1
+ Type: SHT_NOTE
+ AddressAlign: [[ALIGN]]
+ Notes:
- Name: CORE
Type: 0x03
Desc: 0303
- Name: CORE
Type: 0x04
Desc: 0404
+ - Name: .note2
+ Type: SHT_NOTE
+ AddressAlign: [[ALIGN]]
+ Notes:
- Name: LINUX
Type: 0x01
Desc: 0505
>From 1c84760cbce5a9815fc385de58b9e6f0ffccf1ee Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Thu, 19 Dec 2024 19:52:07 -0800
Subject: [PATCH 06/11] fixup: split 'removeNote()'
---
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 179 ++++++++++++++++------------
llvm/lib/ObjCopy/ELF/ELFObject.h | 8 +-
2 files changed, 107 insertions(+), 80 deletions(-)
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 1df64b0b7ce886..9401310bf27507 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -609,95 +609,122 @@ static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,
Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
}
+namespace {
+struct RemoveNoteDetail {
+ struct DeletedRange {
+ uint64_t OldFrom;
+ uint64_t OldTo;
+ uint64_t NewPos;
+ };
+
+ template <class ELFT>
+ static std::vector<DeletedRange>
+ findNotesToRemove(ArrayRef<uint8_t> Data, size_t Align,
+ ArrayRef<RemoveNoteInfo> NotesToRemove);
+ static std::vector<uint8_t> updateData(ArrayRef<uint8_t> OldData,
+ ArrayRef<DeletedRange> ToRemove);
+ static Object::Section2OffsetAndSize
+ getSectionMapping(const Segment &Seg, ArrayRef<DeletedRange> ToRemove);
+};
+
+} // namespace
+
template <class ELFT>
-static Error removeNoteImpl(Object &Obj,
- ArrayRef<RemoveNoteInfo> NotesToRemove) {
+std::vector<RemoveNoteDetail::DeletedRange>
+RemoveNoteDetail::findNotesToRemove(ArrayRef<uint8_t> Data, size_t Align,
+ ArrayRef<RemoveNoteInfo> NotesToRemove) {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT);
- for (Segment &Seg : Obj.segments()) {
- // TODO: Support nested segments
- if (Seg.Type != PT_NOTE || Seg.ParentSegment)
- continue;
-
- // Find chunks of the segment data to remove
- struct DeletedRange {
- uint64_t OldFrom;
- uint64_t OldTo;
- uint64_t NewOffset;
- };
- std::vector<DeletedRange> DataToRemove;
- ArrayRef<uint8_t> OldData = Seg.getContents();
- size_t Align = std::max<size_t>(4, Seg.Align);
- uint64_t Offset = 0;
- while (Offset + sizeof(Elf_Nhdr) <= OldData.size()) {
- auto Nhdr = reinterpret_cast<const Elf_Nhdr *>(OldData.data() + Offset);
- size_t FullSize = Nhdr->getSize(Align);
- if (Offset + FullSize > OldData.size())
- break;
- Elf_Note Note(*Nhdr);
- if (llvm::any_of(NotesToRemove, [&](const RemoveNoteInfo &NoteInfo) {
- return NoteInfo.TypeId == Note.getType() &&
- (NoteInfo.Name.empty() || NoteInfo.Name == Note.getName());
- }))
- DataToRemove.push_back({Offset, Offset + FullSize, 0});
- Offset += FullSize;
- }
- if (DataToRemove.empty())
- continue;
+ std::vector<DeletedRange> ToRemove;
+ uint64_t CurPos = 0;
+ uint64_t NewPos = 0;
+ while (CurPos + sizeof(Elf_Nhdr) <= Data.size()) {
+ auto Nhdr = reinterpret_cast<const Elf_Nhdr *>(Data.data() + CurPos);
+ size_t FullSize = Nhdr->getSize(Align);
+ if (CurPos + FullSize > Data.size())
+ break;
+ Elf_Note Note(*Nhdr);
+ bool ShouldRemove =
+ llvm::any_of(NotesToRemove, [&Note](const RemoveNoteInfo &NoteInfo) {
+ return NoteInfo.TypeId == Note.getType() &&
+ (NoteInfo.Name.empty() || NoteInfo.Name == Note.getName());
+ });
+ if (ShouldRemove)
+ ToRemove.push_back({CurPos, CurPos + FullSize, NewPos});
+ else
+ NewPos += FullSize;
+ CurPos += FullSize;
+ }
+ return ToRemove;
+}
- // Prepare the new segment data
- std::vector<uint8_t> NewData;
- NewData.reserve(OldData.size());
- Offset = 0;
- for (auto &RemRange : DataToRemove) {
- if (Offset < RemRange.OldFrom) {
- auto Slice = OldData.slice(Offset, RemRange.OldFrom - Offset);
- NewData.insert(NewData.end(), Slice.begin(), Slice.end());
- }
- RemRange.NewOffset = NewData.size();
- Offset = RemRange.OldTo;
- }
- if (Offset < OldData.size()) {
- auto Slice = OldData.slice(Offset);
+std::vector<uint8_t>
+RemoveNoteDetail::updateData(ArrayRef<uint8_t> OldData,
+ ArrayRef<DeletedRange> ToRemove) {
+ std::vector<uint8_t> NewData;
+ NewData.reserve(OldData.size());
+ uint64_t CurPos = 0;
+ for (auto &RemRange : ToRemove) {
+ if (CurPos < RemRange.OldFrom) {
+ auto Slice = OldData.slice(CurPos, RemRange.OldFrom - CurPos);
NewData.insert(NewData.end(), Slice.begin(), Slice.end());
}
+ assert(RemRange.NewPos == NewData.size());
+ CurPos = RemRange.OldTo;
+ }
+ if (CurPos < OldData.size()) {
+ auto Slice = OldData.slice(CurPos);
+ NewData.insert(NewData.end(), Slice.begin(), Slice.end());
+ }
+ return NewData;
+}
- auto CalculateNewOffset = [&](uint64_t SecOffset) {
- uint64_t Offset = SecOffset - Seg.Offset;
- auto It =
- llvm::upper_bound(DataToRemove, Offset,
- [](const uint64_t &Off, const DeletedRange &Range) {
- return Off < Range.OldFrom;
- });
- if (It != DataToRemove.begin()) {
- --It;
- Offset = (Offset > It->OldTo) ? (Offset - It->OldTo + It->NewOffset)
- : It->NewOffset;
- }
- return Offset + Seg.Offset;
- };
-
- // Remap the segment's sections
- DenseMap<const SectionBase *, std::pair<uint64_t, uint64_t>> Mapping;
- for (const SectionBase *Sec : Seg.Sections) {
- uint64_t NewOffset = CalculateNewOffset(Sec->Offset);
- uint64_t NewSize =
- CalculateNewOffset(Sec->Offset + Sec->Size) - NewOffset;
- Mapping.try_emplace(Sec, NewOffset, NewSize);
+Object::Section2OffsetAndSize
+RemoveNoteDetail::getSectionMapping(const Segment &Seg,
+ ArrayRef<DeletedRange> ToRemove) {
+ auto CalculateNewOffset = [&](uint64_t SecOffset) {
+ uint64_t Pos = SecOffset - Seg.Offset;
+ auto It = llvm::upper_bound(
+ ToRemove, Pos, [](const uint64_t &Pos, const DeletedRange &Range) {
+ return Pos < Range.OldFrom;
+ });
+ if (It != ToRemove.begin()) {
+ --It;
+ Pos = (Pos > It->OldTo) ? (Pos - It->OldTo + It->NewPos) : It->NewPos;
}
+ return Pos + Seg.Offset;
+ };
- Obj.updateSegmentData(Seg, std::move(NewData), Mapping);
+ // Remap the segment's sections
+ Object::Section2OffsetAndSize Mapping;
+ for (const SectionBase *Sec : Seg.Sections) {
+ uint64_t NewOffset = CalculateNewOffset(Sec->Offset);
+ uint64_t NewSize = CalculateNewOffset(Sec->Offset + Sec->Size) - NewOffset;
+ Mapping.try_emplace(Sec, NewOffset, NewSize);
}
- return Error::success();
+ return Mapping;
}
static Error removeNote(Object &Obj, endianness Endianness,
ArrayRef<RemoveNoteInfo> NotesToRemove) {
- // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
- // header, so the parsers are the same.
- if (Endianness == endianness::little)
- return removeNoteImpl<ELF64LE>(Obj, NotesToRemove);
- else
- return removeNoteImpl<ELF64BE>(Obj, NotesToRemove);
+ for (Segment &Seg : Obj.segments()) {
+ // TODO: Support nested segments
+ if (Seg.Type != PT_NOTE || Seg.ParentSegment)
+ continue;
+ ArrayRef<uint8_t> OldData = Seg.getContents();
+ size_t Align = std::max<size_t>(4, Seg.Align);
+ // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
+ // header, so the parsers are the same.
+ auto ToRemove = (Endianness == endianness::little)
+ ? RemoveNoteDetail::findNotesToRemove<ELF64LE>(
+ OldData, Align, NotesToRemove)
+ : RemoveNoteDetail::findNotesToRemove<ELF64BE>(
+ OldData, Align, NotesToRemove);
+ if (!ToRemove.empty())
+ Obj.updateSegmentData(Seg,
+ RemoveNoteDetail::updateData(OldData, ToRemove),
+ RemoveNoteDetail::getSectionMapping(Seg, ToRemove));
+ }
+ return Error::success();
}
static Error
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 5e16d4c0c1885a..fc518327c1be11 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -1235,10 +1235,10 @@ class Object {
Segments.emplace_back(std::make_unique<Segment>(Data));
return *Segments.back();
}
- void updateSegmentData(
- Segment &S, std::vector<uint8_t> NewSegmentData,
- const DenseMap<const SectionBase *, std::pair<uint64_t, uint64_t>>
- &SectionMapping);
+ using OffsetAndSize = std::pair<uint64_t, uint64_t>;
+ using Section2OffsetAndSize = DenseMap<const SectionBase *, OffsetAndSize>;
+ void updateSegmentData(Segment &S, std::vector<uint8_t> NewSegmentData,
+ const Section2OffsetAndSize &SectionMapping);
bool isRelocatable() const {
return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
}
>From f6d4330cf26dad70e4fb08ff319ffd8c5f057349 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Thu, 19 Dec 2024 20:16:22 -0800
Subject: [PATCH 07/11] fixup: do not allow '--remove-note' with
'--(remove|add|update)-section'
---
llvm/test/tools/llvm-objcopy/ELF/remove-note.test | 10 ++++++++++
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 15 +++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
index 8475e3f8c31737..6eaeda9528a86d 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -1,3 +1,13 @@
+## Check incompatible options
+# RUN: not llvm-objcopy --remove-note=1 --remove-section=.test - 2>&1 | FileCheck %s --check-prefix=ERR-REMSEC
+# RUN: not llvm-objcopy --remove-note=1 --add-section=.test=%s - 2>&1 | FileCheck %s --check-prefix=ERR-ADDSEC
+# RUN: not llvm-objcopy --remove-note=1 --update-section=.test=%s - 2>&1 | FileCheck %s --check-prefix=ERR-UPDSEC
+
+# ERR-REMSEC: error: cannot specify both --remove-note and --remove-section
+# ERR-ADDSEC: error: cannot specify both --remove-note and --add-section
+# ERR-UPDSEC: error: cannot specify both --remove-note and --update-section
+
+## Check invalid argument formats
# RUN: not llvm-objcopy --remove-note= - 2>&1 | FileCheck %s --check-prefix=ERR-NOTYPEID
# RUN: not llvm-objcopy --remove-note=CORE/ - 2>&1 | FileCheck %s --check-prefix=ERR-NOTYPEID
# RUN: not llvm-objcopy --remove-note=/1 - 2>&1 | FileCheck %s --check-prefix=ERR-EMPTYNAME
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index a5643f0bec5d92..0d209590655ef3 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -1261,6 +1261,21 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
ELFConfig.NotesToRemove.push_back(*NoteInfo);
}
+ if (!ELFConfig.NotesToRemove.empty()) {
+ if (!Config.ToRemove.empty())
+ return createStringError(
+ errc::invalid_argument,
+ "cannot specify both --remove-note and --remove-section");
+ if (!Config.AddSection.empty())
+ return createStringError(
+ errc::invalid_argument,
+ "cannot specify both --remove-note and --add-section");
+ if (!Config.UpdateSection.empty())
+ return createStringError(
+ errc::invalid_argument,
+ "cannot specify both --remove-note and --update-section");
+ }
+
if (Config.DecompressDebugSections &&
Config.CompressionType != DebugCompressionType::None) {
return createStringError(
>From fd72505eb22a4320463ed01fb54ed15a1c44c24b Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 20 Dec 2024 19:33:59 -0800
Subject: [PATCH 08/11] fixup: change ELF type of the test file ET_CORE ->
ET_EXEC
For core files, llvm-readobj dumps note segments as a whole,
without reporting individual sections.
---
.../tools/llvm-objcopy/ELF/remove-note.test | 24 +++++++++++++++----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
index 6eaeda9528a86d..768949e2687f07 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -63,35 +63,49 @@
# CHECK: NoteSections [
# CHECK-NEXT: NoteSection {
-# CHECK-NEXT: Name:
+# CHECK-NEXT: Name: .note0
# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0]]
-# CHECK-NEXT: Size: 0x[[#%X,SIZE0+SIZE1]]
+# CHECK-NEXT: Size: 0x[[#%X,SIZE0]]
# CHECK-NEXT: Notes [
# CHECK-NEXT: {
# CHECK-NEXT: Owner: CORE
# CHECK-NEXT: Data size: 0x2
-# CHECK-NEXT: Type: NT_FPREGSET
+# CHECK-NEXT: Type: NT_ARCH
# CHECK-NEXT: Description data (
# CHECK-NEXT: 0000: 0202
# CHECK-NEXT: )
# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
+# CHECK-NEXT: NoteSection {
+# CHECK-NEXT: Name: .note1
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0]]
+# CHECK-NEXT: Size: 0x[[#%X,SIZE1]]
+# CHECK-NEXT: Notes [
# CHECK-NEXT: {
# CHECK-NEXT: Owner: CORE
# CHECK-NEXT: Data size: 0x2
-# CHECK-NEXT: Type: NT_TASKSTRUCT
+# CHECK-NEXT: Type: Unknown (0x00000004)
# CHECK-NEXT: Description data (
# CHECK-NEXT: 0000: 0404
# CHECK-NEXT: )
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
+# CHECK-NEXT: NoteSection {
+# CHECK-NEXT: Name: .note2
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0+SIZE1]]
+# CHECK-NEXT: Size: 0x0
+# CHECK-NEXT: Notes [
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
# CHECK-NEXT: ]
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
- Type: ET_CORE
+ Type: ET_EXEC
Machine: EM_X86_64
ProgramHeaders:
- Type: PT_NOTE
>From e730cfdaf0ffe463c2692d3dbf98c6da1a0a06bc Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 20 Dec 2024 19:44:47 -0800
Subject: [PATCH 09/11] fixup: also run the test for ELF32 and BE
---
.../tools/llvm-objcopy/ELF/remove-note.test | 23 ++++++++++++-------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
index 768949e2687f07..2053e76593fad1 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -20,13 +20,20 @@
# ERR-INVNUM1: error: bad note type_id for --remove-note: '1/2'
# ERR-INVNUM2: error: bad note type_id for --remove-note: 'Notanumber'
-# RUN: yaml2obj -D ALIGN=8 %s -o %t8
-# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/2 --remove-note=CORE/0x03 %t8 %t8o
-# RUN: llvm-readobj --segments --sections --notes %t8o | FileCheck %s -D#SIZE0=32 -D#SIZE1=32
+# RUN: yaml2obj -D ALIGN=8 -D ELFCLASS=64 -D ENDIANNESS=LSB %s -o %t8.64.lsb
+# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/2 --remove-note=CORE/0x03 %t8.64.lsb %t8.64.lsb.o
+# RUN: llvm-readobj --segments --sections --notes %t8.64.lsb.o | \
+# RUN: FileCheck %s -D#SIZE0=32 -D#SIZE1=32
-# RUN: yaml2obj -D ALIGN=4 %s -o %t4
-# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4 %t4o
-# RUN: llvm-readobj --segments --sections --notes %t4o | FileCheck %s -D#SIZE0=24 -D#SIZE1=24
+# RUN: yaml2obj -D ALIGN=4 -D ELFCLASS=64 -D ENDIANNESS=MSB %s -o %t4.64.msb
+# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4.64.msb %t4.64.msb.o
+# RUN: llvm-readobj --segments --sections --notes %t4.64.msb.o | \
+# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24
+
+# RUN: yaml2obj -D ALIGN=4 -D ELFCLASS=32 -D ENDIANNESS=LSB %s -o %t4.32.lsb
+# RUN: llvm-objcopy --remove-note=1 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4.32.lsb %t4.32.lsb.o
+# RUN: llvm-readobj --segments --sections --notes %t4.32.lsb.o | \
+# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24
# CHECK: Sections [
# CHECK: Section {
@@ -103,8 +110,8 @@
--- !ELF
FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
+ Class: ELFCLASS[[ELFCLASS]]
+ Data: ELFDATA2[[ENDIANNESS]]
Type: ET_EXEC
Machine: EM_X86_64
ProgramHeaders:
>From de674542e110dd27a1e42c42301b53aad089efad Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 20 Dec 2024 19:46:44 -0800
Subject: [PATCH 10/11] fixup: handle SHT_NOTE sections outside of segments
---
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 18 ++++++++
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 29 +++++++++----
llvm/lib/ObjCopy/ELF/ELFObject.h | 8 ++++
.../tools/llvm-objcopy/ELF/remove-note.test | 41 +++++++++++++++++--
4 files changed, 84 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 9401310bf27507..e7c5cff489d94c 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -724,6 +724,24 @@ static Error removeNote(Object &Obj, endianness Endianness,
RemoveNoteDetail::updateData(OldData, ToRemove),
RemoveNoteDetail::getSectionMapping(Seg, ToRemove));
}
+ for (auto &Sec : Obj.sections()) {
+ if (Sec.Type != SHT_NOTE || Sec.ParentSegment || !Sec.hasContents())
+ continue;
+ ArrayRef<uint8_t> OldData = Sec.getContents();
+ size_t Align = std::max<size_t>(4, Sec.Align);
+ // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
+ // header, so the parsers are the same.
+ auto ToRemove = (Endianness == endianness::little)
+ ? RemoveNoteDetail::findNotesToRemove<ELF64LE>(
+ OldData, Align, NotesToRemove)
+ : RemoveNoteDetail::findNotesToRemove<ELF64BE>(
+ OldData, Align, NotesToRemove);
+ if (!ToRemove.empty()) {
+ if (Error E = Obj.updateSectionData(
+ Sec, RemoveNoteDetail::updateData(OldData, ToRemove)))
+ return E;
+ }
+ }
return Error::success();
}
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 5f2cef8ac86046..8e547fe5529311 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2154,25 +2154,20 @@ ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH,
: Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
OnlyKeepDebug(OnlyKeepDebug) {}
-Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
- auto It = llvm::find_if(Sections,
- [&](const SecPtr &Sec) { return Sec->Name == Name; });
- if (It == Sections.end())
- return createStringError(errc::invalid_argument, "section '%s' not found",
- Name.str().c_str());
-
+Error Object::updateSectionData(std::vector<SecPtr>::iterator It,
+ ArrayRef<uint8_t> Data) {
auto *OldSec = It->get();
if (!OldSec->hasContents())
return createStringError(
errc::invalid_argument,
"section '%s' cannot be updated because it does not have contents",
- Name.str().c_str());
+ OldSec->Name.c_str());
if (Data.size() > OldSec->Size && OldSec->ParentSegment)
return createStringError(errc::invalid_argument,
"cannot fit data of size %zu into section '%s' "
"with size %" PRIu64 " that is part of a segment",
- Data.size(), Name.str().c_str(), OldSec->Size);
+ Data.size(), OldSec->Name.c_str(), OldSec->Size);
if (!OldSec->ParentSegment) {
*It = std::make_unique<OwnedDataSection>(*OldSec, Data);
@@ -2185,6 +2180,22 @@ Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
return Error::success();
}
+Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
+ auto It = llvm::find_if(Sections,
+ [&](const SecPtr &Sec) { return Sec->Name == Name; });
+ if (It == Sections.end())
+ return createStringError(errc::invalid_argument, "section '%s' not found",
+ Name.str().c_str());
+ return updateSectionData(It, Data);
+}
+
+Error Object::updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data) {
+ auto It = llvm::find_if(Sections,
+ [&](const SecPtr &Sec) { return Sec.get() == &S; });
+ assert(It != Sections.end() && "The section should belong to the object");
+ return updateSectionData(It, Data);
+}
+
Error Object::removeSections(
bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index fc518327c1be11..285dd0bc12445c 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -549,6 +549,7 @@ class SectionBase {
virtual void
replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
virtual bool hasContents() const { return false; }
+ virtual ArrayRef<uint8_t> getContents() const { return {}; }
// Notify the section that it is subject to removal.
virtual void onRemove();
@@ -619,6 +620,8 @@ class Section : public SectionBase {
bool hasContents() const override {
return Type != ELF::SHT_NOBITS && Type != ELF::SHT_NULL;
}
+ ArrayRef<uint8_t> getContents() const override { return Contents; }
+
void restoreSymTabLink(SymbolTableSection &SymTab) override;
};
@@ -654,6 +657,7 @@ class OwnedDataSection : public SectionBase {
Error accept(SectionVisitor &Sec) const override;
Error accept(MutableSectionVisitor &Visitor) override;
bool hasContents() const override { return true; }
+ ArrayRef<uint8_t> getContents() const override { return Data; }
};
class CompressedSection : public SectionBase {
@@ -1165,6 +1169,9 @@ class Object {
return Sec.Flags & ELF::SHF_ALLOC;
};
+ Error updateSectionData(std::vector<SecPtr>::iterator SecIt,
+ ArrayRef<uint8_t> Data);
+
public:
template <class T>
using ConstRange = iterator_range<pointee_iterator<
@@ -1207,6 +1214,7 @@ class Object {
const auto &getUpdatedSections() const { return UpdatedSections; }
Error updateSection(StringRef Name, ArrayRef<uint8_t> Data);
+ Error updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data);
SectionBase *findSection(StringRef Name) {
auto SecIt =
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
index 2053e76593fad1..ecb39dba5ab6de 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -23,17 +23,17 @@
# RUN: yaml2obj -D ALIGN=8 -D ELFCLASS=64 -D ENDIANNESS=LSB %s -o %t8.64.lsb
# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/2 --remove-note=CORE/0x03 %t8.64.lsb %t8.64.lsb.o
# RUN: llvm-readobj --segments --sections --notes %t8.64.lsb.o | \
-# RUN: FileCheck %s -D#SIZE0=32 -D#SIZE1=32
+# RUN: FileCheck %s -D#SIZE0=32 -D#SIZE1=32 -D#SIZE3=32
# RUN: yaml2obj -D ALIGN=4 -D ELFCLASS=64 -D ENDIANNESS=MSB %s -o %t4.64.msb
# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4.64.msb %t4.64.msb.o
# RUN: llvm-readobj --segments --sections --notes %t4.64.msb.o | \
-# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24
+# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24 -D#SIZE3=24
# RUN: yaml2obj -D ALIGN=4 -D ELFCLASS=32 -D ENDIANNESS=LSB %s -o %t4.32.lsb
# RUN: llvm-objcopy --remove-note=1 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4.32.lsb %t4.32.lsb.o
# RUN: llvm-readobj --segments --sections --notes %t4.32.lsb.o | \
-# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24
+# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24 -D#SIZE3=24
# CHECK: Sections [
# CHECK: Section {
@@ -58,6 +58,13 @@
# CHECK-NEXT: Address:
# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0+SIZE1]]
# CHECK-NEXT: Size: 0
+# CHECK: Name: .note3
+# CHECK-NEXT: Type: SHT_NOTE
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET3:]]
+# CHECK-NEXT: Size: [[#%d,SIZE3]]
# CHECK: ProgramHeaders [
# CHECK-NEXT: ProgramHeader {
@@ -106,6 +113,21 @@
# CHECK-NEXT: Notes [
# CHECK-NEXT: ]
# CHECK-NEXT: }
+# CHECK-NEXT: NoteSection {
+# CHECK-NEXT: Name: .note3
+# CHECK-NEXT: Offset: 0x[[#%X,OFFSET3]]
+# CHECK-NEXT: Size: 0x[[#%X,SIZE3]]
+# CHECK-NEXT: Notes [
+# CHECK-NEXT: {
+# CHECK-NEXT: Owner: CORE
+# CHECK-NEXT: Data size: 0x2
+# CHECK-NEXT: Type: NT_ARCH
+# CHECK-NEXT: Description data (
+# CHECK-NEXT: 0000: 0707
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
# CHECK-NEXT: ]
--- !ELF
@@ -147,4 +169,17 @@ Sections:
- Name: LINUX
Type: 0x01
Desc: 0505
+ - Name: .note3
+ Type: SHT_NOTE
+ AddressAlign: [[ALIGN]]
+ Notes:
+ - Name: GNU
+ Type: 0x01
+ Desc: 0606
+ - Name: CORE
+ Type: 0x02
+ Desc: 0707
+ - Name: CORE
+ Type: 0x03
+ Desc: 0808
...
>From 95b6b9407a16f006bf2fbec0452eb10089a45c58 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Mon, 23 Dec 2024 12:50:20 -0800
Subject: [PATCH 11/11] Remove handling for segments
---
llvm/docs/CommandGuide/llvm-objcopy.rst | 2 +-
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 47 +------------
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 28 --------
llvm/lib/ObjCopy/ELF/ELFObject.h | 5 --
.../tools/llvm-objcopy/ELF/remove-note.test | 70 +++----------------
5 files changed, 12 insertions(+), 140 deletions(-)
diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index c57d367261a121..166525047d1f54 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -467,7 +467,7 @@ them.
.. option:: --remove-note [<name>/]<type>
Remove notes of integer type ``<type>`` and name ``<name>`` from SHT_NOTE
- sections and PT_NOTE segments. Can be specified multiple times.
+ sections that are not in a segment. Can be specified multiple times.
.. option:: --rename-section <old>=<new>[,<flag>,...]
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index e7c5cff489d94c..74380bab0e4461 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -623,8 +623,6 @@ struct RemoveNoteDetail {
ArrayRef<RemoveNoteInfo> NotesToRemove);
static std::vector<uint8_t> updateData(ArrayRef<uint8_t> OldData,
ArrayRef<DeletedRange> ToRemove);
- static Object::Section2OffsetAndSize
- getSectionMapping(const Segment &Seg, ArrayRef<DeletedRange> ToRemove);
};
} // namespace
@@ -678,53 +676,10 @@ RemoveNoteDetail::updateData(ArrayRef<uint8_t> OldData,
return NewData;
}
-Object::Section2OffsetAndSize
-RemoveNoteDetail::getSectionMapping(const Segment &Seg,
- ArrayRef<DeletedRange> ToRemove) {
- auto CalculateNewOffset = [&](uint64_t SecOffset) {
- uint64_t Pos = SecOffset - Seg.Offset;
- auto It = llvm::upper_bound(
- ToRemove, Pos, [](const uint64_t &Pos, const DeletedRange &Range) {
- return Pos < Range.OldFrom;
- });
- if (It != ToRemove.begin()) {
- --It;
- Pos = (Pos > It->OldTo) ? (Pos - It->OldTo + It->NewPos) : It->NewPos;
- }
- return Pos + Seg.Offset;
- };
-
- // Remap the segment's sections
- Object::Section2OffsetAndSize Mapping;
- for (const SectionBase *Sec : Seg.Sections) {
- uint64_t NewOffset = CalculateNewOffset(Sec->Offset);
- uint64_t NewSize = CalculateNewOffset(Sec->Offset + Sec->Size) - NewOffset;
- Mapping.try_emplace(Sec, NewOffset, NewSize);
- }
- return Mapping;
-}
-
static Error removeNote(Object &Obj, endianness Endianness,
ArrayRef<RemoveNoteInfo> NotesToRemove) {
- for (Segment &Seg : Obj.segments()) {
- // TODO: Support nested segments
- if (Seg.Type != PT_NOTE || Seg.ParentSegment)
- continue;
- ArrayRef<uint8_t> OldData = Seg.getContents();
- size_t Align = std::max<size_t>(4, Seg.Align);
- // Note: notes for both 32-bit and 64-bit ELF files use 4-byte words in the
- // header, so the parsers are the same.
- auto ToRemove = (Endianness == endianness::little)
- ? RemoveNoteDetail::findNotesToRemove<ELF64LE>(
- OldData, Align, NotesToRemove)
- : RemoveNoteDetail::findNotesToRemove<ELF64BE>(
- OldData, Align, NotesToRemove);
- if (!ToRemove.empty())
- Obj.updateSegmentData(Seg,
- RemoveNoteDetail::updateData(OldData, ToRemove),
- RemoveNoteDetail::getSectionMapping(Seg, ToRemove));
- }
for (auto &Sec : Obj.sections()) {
+ // TODO: Support note sections in segments
if (Sec.Type != SHT_NOTE || Sec.ParentSegment || !Sec.hasContents())
continue;
ArrayRef<uint8_t> OldData = Sec.getContents();
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 8e547fe5529311..2c7a39779220e5 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2319,34 +2319,6 @@ Error Object::addNewSymbolTable() {
return Error::success();
}
-void Object::updateSegmentData(
- Segment &S, std::vector<uint8_t> NewSegmentData,
- const DenseMap<const SectionBase *, std::pair<uint64_t, uint64_t>>
- &SectionMapping) {
- // TODO: Update the parent segment
- assert(!S.ParentSegment);
- // TODO: Update nested segments
- assert(!llvm::any_of(
- Segments, [&S](const SegPtr &Seg) { return Seg->ParentSegment == &S; }));
- auto It =
- UpdatedSegments.insert_or_assign(&S, std::move(NewSegmentData)).first;
- S.Contents = It->second;
- S.FileSize = S.Contents.size();
- if (S.MemSize)
- S.MemSize = S.FileSize;
- assert(SectionMapping.size() == S.Sections.size());
- assert(S.Offset == S.OriginalOffset);
- for (const auto &SM : SectionMapping) {
- assert(SM.first->ParentSegment == &S && S.Sections.count(SM.first));
- assert(SM.second.first >= S.Offset);
- assert((SM.second.first + SM.second.second) <= (S.Offset + S.FileSize));
- assert(SM.first->Offset == SM.first->OriginalOffset);
- SectionBase *MutSec = const_cast<SectionBase *>(SM.first);
- MutSec->OriginalOffset = MutSec->Offset = SM.second.first;
- MutSec->Size = SM.second.second;
- }
-}
-
// Orders segments such that if x = y->ParentSegment then y comes before x.
static void orderSegments(std::vector<Segment *> &Segments) {
llvm::stable_sort(Segments, compareSegmentsByOffset);
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 285dd0bc12445c..8908187673b024 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -1163,7 +1163,6 @@ class Object {
std::vector<SegPtr> Segments;
std::vector<SecPtr> RemovedSections;
DenseMap<SectionBase *, std::vector<uint8_t>> UpdatedSections;
- DenseMap<Segment *, std::vector<uint8_t>> UpdatedSegments;
static bool sectionIsAlloc(const SectionBase &Sec) {
return Sec.Flags & ELF::SHF_ALLOC;
@@ -1243,10 +1242,6 @@ class Object {
Segments.emplace_back(std::make_unique<Segment>(Data));
return *Segments.back();
}
- using OffsetAndSize = std::pair<uint64_t, uint64_t>;
- using Section2OffsetAndSize = DenseMap<const SectionBase *, OffsetAndSize>;
- void updateSegmentData(Segment &S, std::vector<uint8_t> NewSegmentData,
- const Section2OffsetAndSize &SectionMapping);
bool isRelocatable() const {
return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
}
diff --git a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
index ecb39dba5ab6de..9ad873066a73e5 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/remove-note.test
@@ -23,17 +23,17 @@
# RUN: yaml2obj -D ALIGN=8 -D ELFCLASS=64 -D ENDIANNESS=LSB %s -o %t8.64.lsb
# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/2 --remove-note=CORE/0x03 %t8.64.lsb %t8.64.lsb.o
# RUN: llvm-readobj --segments --sections --notes %t8.64.lsb.o | \
-# RUN: FileCheck %s -D#SIZE0=32 -D#SIZE1=32 -D#SIZE3=32
+# RUN: FileCheck %s -D#SIZE0=32 -D#SIZE1=32
# RUN: yaml2obj -D ALIGN=4 -D ELFCLASS=64 -D ENDIANNESS=MSB %s -o %t4.64.msb
# RUN: llvm-objcopy --remove-note=0x01 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4.64.msb %t4.64.msb.o
# RUN: llvm-readobj --segments --sections --notes %t4.64.msb.o | \
-# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24 -D#SIZE3=24
+# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24
# RUN: yaml2obj -D ALIGN=4 -D ELFCLASS=32 -D ENDIANNESS=LSB %s -o %t4.32.lsb
# RUN: llvm-objcopy --remove-note=1 --remove-note=DUMMY/0x02 --remove-note=CORE/3 %t4.32.lsb %t4.32.lsb.o
# RUN: llvm-readobj --segments --sections --notes %t4.32.lsb.o | \
-# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24 -D#SIZE3=24
+# RUN: FileCheck %s -D#SIZE0=24 -D#SIZE1=24
# CHECK: Sections [
# CHECK: Section {
@@ -42,43 +42,27 @@
# CHECK-NEXT: Flags [
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0:]]
+# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: [[#%d,SIZE0]]
# CHECK: Name: .note1
# CHECK-NEXT: Type: SHT_NOTE
# CHECK-NEXT: Flags [
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0]]
+# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: [[#%d,SIZE1]]
# CHECK: Name: .note2
# CHECK-NEXT: Type: SHT_NOTE
# CHECK-NEXT: Flags [
# CHECK-NEXT: ]
# CHECK-NEXT: Address:
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0+SIZE1]]
+# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 0
-# CHECK: Name: .note3
-# CHECK-NEXT: Type: SHT_NOTE
-# CHECK-NEXT: Flags [
-# CHECK-NEXT: ]
-# CHECK-NEXT: Address:
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET3:]]
-# CHECK-NEXT: Size: [[#%d,SIZE3]]
-
-# CHECK: ProgramHeaders [
-# CHECK-NEXT: ProgramHeader {
-# CHECK-NEXT: Type: PT_NOTE
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0]]
-# CHECK-NEXT: VirtualAddress: 0x0
-# CHECK-NEXT: PhysicalAddress: 0x0
-# CHECK-NEXT: FileSize: [[#%d,SIZE0+SIZE1]]
-# CHECK-NEXT: MemSize: 0
# CHECK: NoteSections [
# CHECK-NEXT: NoteSection {
# CHECK-NEXT: Name: .note0
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0]]
+# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 0x[[#%X,SIZE0]]
# CHECK-NEXT: Notes [
# CHECK-NEXT: {
@@ -93,7 +77,7 @@
# CHECK-NEXT: }
# CHECK-NEXT: NoteSection {
# CHECK-NEXT: Name: .note1
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0]]
+# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 0x[[#%X,SIZE1]]
# CHECK-NEXT: Notes [
# CHECK-NEXT: {
@@ -108,39 +92,18 @@
# CHECK-NEXT: }
# CHECK-NEXT: NoteSection {
# CHECK-NEXT: Name: .note2
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET0+SIZE0+SIZE1]]
+# CHECK-NEXT: Offset:
# CHECK-NEXT: Size: 0x0
# CHECK-NEXT: Notes [
# CHECK-NEXT: ]
# CHECK-NEXT: }
-# CHECK-NEXT: NoteSection {
-# CHECK-NEXT: Name: .note3
-# CHECK-NEXT: Offset: 0x[[#%X,OFFSET3]]
-# CHECK-NEXT: Size: 0x[[#%X,SIZE3]]
-# CHECK-NEXT: Notes [
-# CHECK-NEXT: {
-# CHECK-NEXT: Owner: CORE
-# CHECK-NEXT: Data size: 0x2
-# CHECK-NEXT: Type: NT_ARCH
-# CHECK-NEXT: Description data (
-# CHECK-NEXT: 0000: 0707
-# CHECK-NEXT: )
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
-# CHECK-NEXT: }
-# CHECK-NEXT: ]
--- !ELF
FileHeader:
Class: ELFCLASS[[ELFCLASS]]
Data: ELFDATA2[[ENDIANNESS]]
- Type: ET_EXEC
+ Type: ET_REL
Machine: EM_X86_64
-ProgramHeaders:
- - Type: PT_NOTE
- MemSize: 0
- FirstSec: .note0
- LastSec: .note2
Sections:
- Name: .note0
Type: SHT_NOTE
@@ -169,17 +132,4 @@ Sections:
- Name: LINUX
Type: 0x01
Desc: 0505
- - Name: .note3
- Type: SHT_NOTE
- AddressAlign: [[ALIGN]]
- Notes:
- - Name: GNU
- Type: 0x01
- Desc: 0606
- - Name: CORE
- Type: 0x02
- Desc: 0707
- - Name: CORE
- Type: 0x03
- Desc: 0808
...
More information about the llvm-commits
mailing list