[llvm] [llvm-objcopy][ELF] Disable huge section offset (PR #97036)
Djordje Todorovic via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 6 03:54:07 PDT 2024
https://github.com/djtodoro updated https://github.com/llvm/llvm-project/pull/97036
>From ef48e9051b29a162a6207a3d9591b63a647539fe Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic at syrmia.com>
Date: Thu, 20 Jun 2024 18:08:40 +0200
Subject: [PATCH] [llvm-objcopy][ELF] Disable huge section offset
Match GNU objcopy's behavior.
This is controlled by an option, that is set to OFF by default.
---
llvm/include/llvm/ObjCopy/ELF/ELFConfig.h | 1 +
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 15 ++++++-----
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 9 +++++++
llvm/lib/ObjCopy/ELF/ELFObject.h | 11 +++++---
.../ELF/disable-huge-negative-offset.yaml | 27 +++++++++++++++++++
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 2 ++
llvm/tools/llvm-objcopy/ObjcopyOpts.td | 4 +++
7 files changed, 59 insertions(+), 10 deletions(-)
create mode 100644 llvm/test/tools/llvm-objcopy/ELF/disable-huge-negative-offset.yaml
diff --git a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
index 59960b65307430..d82175832672b5 100644
--- a/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
+++ b/llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
@@ -31,6 +31,7 @@ struct ELFConfig {
bool KeepFileSymbols = false;
bool LocalizeHidden = false;
bool VerifyNoteSections = true;
+ bool DisableHugeSectionOffset = false;
};
} // namespace objcopy
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 40598861d42731..22e376bf11d6ca 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -176,11 +176,12 @@ static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config,
}
static std::unique_ptr<Writer> createWriter(const CommonConfig &Config,
+ const ELFConfig &ELFConfig,
Object &Obj, raw_ostream &Out,
ElfType OutputElfType) {
switch (Config.OutputFormat) {
case FileFormat::Binary:
- return std::make_unique<BinaryWriter>(Obj, Out, Config);
+ return std::make_unique<BinaryWriter>(Obj, Out, Config, ELFConfig);
case FileFormat::IHex:
return std::make_unique<IHexWriter>(Obj, Out, Config.OutputFilename);
case FileFormat::SREC:
@@ -926,10 +927,10 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
return Error::success();
}
-static Error writeOutput(const CommonConfig &Config, Object &Obj,
- raw_ostream &Out, ElfType OutputElfType) {
+static Error writeOutput(const CommonConfig &Config, const ELFConfig &ELFConfig,
+ Object &Obj, raw_ostream &Out, ElfType OutputElfType) {
std::unique_ptr<Writer> Writer =
- createWriter(Config, Obj, Out, OutputElfType);
+ createWriter(Config, ELFConfig, Obj, Out, OutputElfType);
if (Error E = Writer->finalize())
return E;
return Writer->write();
@@ -947,7 +948,7 @@ Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))
return E;
- return writeOutput(Config, **Obj, Out, OutputElfType);
+ return writeOutput(Config, ELFConfig, **Obj, Out, OutputElfType);
}
Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
@@ -965,7 +966,7 @@ Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))
return E;
- return writeOutput(Config, **Obj, Out, OutputElfType);
+ return writeOutput(Config, ELFConfig, **Obj, Out, OutputElfType);
}
Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
@@ -985,7 +986,7 @@ Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))
return createFileError(Config.InputFilename, std::move(E));
- if (Error E = writeOutput(Config, **Obj, Out, OutputElfType))
+ if (Error E = writeOutput(Config, ELFConfig, **Obj, Out, OutputElfType))
return createFileError(Config.InputFilename, std::move(E));
return Error::success();
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index fd55f974115a24..e060b4520307f6 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2744,6 +2744,15 @@ Error BinaryWriter::finalize() {
if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
Sec.Offset = Sec.Addr - MinAddr;
TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
+
+ // More or less, this makes sense to do for 32-bit targets.
+ if (DisableHugeSectionOffset and not Obj.Is64Bits) {
+ int FilePosition = Sec.Offset;
+ if (FilePosition < 0)
+ return createStringError(errc::file_too_large,
+ "writing section " + Sec.Name +
+ " at huge (ie negative) file offset");
+ }
}
Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 6ccf85387131e4..19981df25da0f5 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -15,6 +15,7 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/ObjCopy/CommonConfig.h"
+#include "llvm/ObjCopy/ELF/ELFConfig.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileOutputBuffer.h"
@@ -366,12 +367,16 @@ class BinaryWriter : public Writer {
uint64_t TotalSize = 0;
+ bool DisableHugeSectionOffset = false;
+
public:
~BinaryWriter() {}
Error finalize() override;
Error write() override;
- BinaryWriter(Object &Obj, raw_ostream &Out, const CommonConfig &Config)
- : Writer(Obj, Out), GapFill(Config.GapFill), PadTo(Config.PadTo) {}
+ BinaryWriter(Object &Obj, raw_ostream &Out, const CommonConfig &Config,
+ const ELFConfig &ELFConfig)
+ : Writer(Obj, Out), GapFill(Config.GapFill), PadTo(Config.PadTo),
+ DisableHugeSectionOffset(ELFConfig.DisableHugeSectionOffset) {}
};
// A base class for writing ascii hex formats such as srec and ihex.
@@ -667,7 +672,7 @@ class CompressedSection : public SectionBase {
public:
CompressedSection(const SectionBase &Sec,
- DebugCompressionType CompressionType, bool Is64Bits);
+ DebugCompressionType CompressionType, bool Is64Bits);
CompressedSection(ArrayRef<uint8_t> CompressedData, uint32_t ChType,
uint64_t DecompressedSize, uint64_t DecompressedAlign);
diff --git a/llvm/test/tools/llvm-objcopy/ELF/disable-huge-negative-offset.yaml b/llvm/test/tools/llvm-objcopy/ELF/disable-huge-negative-offset.yaml
new file mode 100644
index 00000000000000..5769211e2dd4fc
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/disable-huge-negative-offset.yaml
@@ -0,0 +1,27 @@
+# RUN: yaml2obj %s --docnum=1 -o %t
+# RUN: not llvm-objcopy -O binary %t %t2 --disable-huge-section-offset 2>&1 | FileCheck %s
+
+# CHECK: writing section .high_addr at huge (ie negative) file offset
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_MIPS
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ Content: "00112233445566778899AABBCCDDEEFF"
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE ]
+ Address: 0x2000
+ Content: "112233445566778899AABBCCDDEEFF00"
+ - Name: .high_addr
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE ]
+ Address: 0x80001000
+ Content: "2233445566778899AABBCCDDEEFF0011"
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 26a888c628d9d3..ad7554ca1707f1 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -1054,6 +1054,8 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
Config.ExtractMainPartition =
InputArgs.hasArg(OBJCOPY_extract_main_partition);
ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);
+ ELFConfig.DisableHugeSectionOffset =
+ InputArgs.hasArg(OBJCOPY_disable_huge_section_offsets);
Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
if (auto *Arg =
InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index 434b5ff92324eb..9af8c54b0a8a79 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -150,6 +150,10 @@ def localize_hidden
: Flag<["--"], "localize-hidden">,
HelpText<
"Mark all symbols that have hidden or internal visibility as local">;
+def disable_huge_section_offsets
+ : Flag<["--"], "disable-huge-section-offset">,
+ HelpText<
+ "Emit an error if input section has a huge file offset">;
defm localize_symbol
: Eq<"localize-symbol", "Mark any defined non-common symbol named <symbol> as local">,
MetaVarName<"symbol">;
More information about the llvm-commits
mailing list