Skip to content

Commit

Permalink
[llvm-objcopy][ELF] Disable huge section offset
Browse files Browse the repository at this point in the history
Match GNU objcopy's behavior.
This is controlled by an option.
  • Loading branch information
djtodoro authored and Djordje Todorovic committed Sep 7, 2024
1 parent b09c0f8 commit b39e492
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 9 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/ObjCopy/ELF/ELFConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct ELFConfig {
bool AllowBrokenLinks = false;
bool KeepFileSymbols = false;
bool LocalizeHidden = false;
std::optional<uint64_t> MaxHugeSectionOffset;
};

} // namespace objcopy
Expand Down
15 changes: 8 additions & 7 deletions llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,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);
return std::make_unique<BinaryWriter>(Obj, Out, ELFConfig);
case FileFormat::IHex:
return std::make_unique<IHexWriter>(Obj, Out);
default:
Expand Down Expand Up @@ -765,10 +766,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();
Expand All @@ -786,7 +787,7 @@ Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
if (Error E = handleArgs(Config, ELFConfig, **Obj))
return E;
return writeOutput(Config, **Obj, Out, OutputElfType);
return writeOutput(Config, ELFConfig, **Obj, Out, OutputElfType);
}

Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
Expand All @@ -804,7 +805,7 @@ Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
if (Error E = handleArgs(Config, ELFConfig, **Obj))
return E;
return writeOutput(Config, **Obj, Out, OutputElfType);
return writeOutput(Config, ELFConfig, **Obj, Out, OutputElfType);
}

Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
Expand All @@ -824,7 +825,7 @@ Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
if (Error E = handleArgs(Config, ELFConfig, **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();
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/ObjCopy/ELF/ELFObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2643,6 +2643,13 @@ Error BinaryWriter::finalize() {
if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
Sec.Offset = Sec.Addr - MinAddr;
TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);

if (MaxHugeSectionOffset) {
if (Sec.Offset > *MaxHugeSectionOffset)
return createStringError(errc::file_too_large,
"writing section " + Sec.Name +
" at huge file offset");
}
}

Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
Expand Down
9 changes: 7 additions & 2 deletions llvm/lib/ObjCopy/ELF/ELFObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -361,11 +362,15 @@ class BinaryWriter : public Writer {

uint64_t TotalSize = 0;

std::optional<uint64_t> MaxHugeSectionOffset;

public:
~BinaryWriter() {}
Error finalize() override;
Error write() override;
BinaryWriter(Object &Obj, raw_ostream &Out) : Writer(Obj, Out) {}
BinaryWriter(Object &Obj, raw_ostream &Out, const ELFConfig &ELFConfig)
: Writer(Obj, Out),
MaxHugeSectionOffset(ELFConfig.MaxHugeSectionOffset) {}
};

class IHexWriter : public Writer {
Expand Down Expand Up @@ -544,7 +549,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);

Expand Down
27 changes: 27 additions & 0 deletions llvm/test/tools/llvm-objcopy/ELF/disable-huge-section-offset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# RUN: yaml2obj %s --docnum=1 -o %t
# RUN: not llvm-objcopy -O binary %t %t2 --set-max-huge-section-offset=2000000000 2>&1 | FileCheck %s

# CHECK: writing section .high_addr at huge 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"
5 changes: 5 additions & 0 deletions llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,11 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
Config.ExtractMainPartition =
InputArgs.hasArg(OBJCOPY_extract_main_partition);
ELFConfig.LocalizeHidden = InputArgs.hasArg(OBJCOPY_localize_hidden);

if (auto *Arg = InputArgs.getLastArg(OBJCOPY_set_max_huge_section_offset)) {
ELFConfig.MaxHugeSectionOffset = std::stoull(Arg->getValue());
}

Config.Weaken = InputArgs.hasArg(OBJCOPY_weaken);
if (auto *Arg =
InputArgs.getLastArg(OBJCOPY_discard_all, OBJCOPY_discard_locals)) {
Expand Down
5 changes: 5 additions & 0 deletions llvm/tools/llvm-objcopy/ObjcopyOpts.td
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ def extract_main_partition
: Flag<["--"], "extract-main-partition">,
HelpText<"Extract main partition from the input file">;

defm set_max_huge_section_offset
: Eq<"set-max-huge-section-offset",
"Emit an error if input section has a huge file offset">,
MetaVarName<"offset">;

def localize_hidden
: Flag<["--"], "localize-hidden">,
HelpText<
Expand Down

0 comments on commit b39e492

Please sign in to comment.