Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

llvm-objcopy: Disable huge sec offset #49

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions llvm/docs/CommandGuide/llvm-objcopy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,11 @@ them.
anything following a '#'. Can be specified multiple times to read names from
multiple files.

.. option:: --max-section-offset <value>

Emit an error if input section has a file offset greater than the specified
``<value>``.

.. option:: --new-symbol-visibility <visibility>

Specify the visibility of the symbols automatically created when using binary
Expand Down
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> MaxSectionOffset;
};

} // 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
9 changes: 9 additions & 0 deletions llvm/lib/ObjCopy/ELF/ELFObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2643,6 +2643,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);

if (MaxSectionOffset && Sec.Offset > *MaxSectionOffset) {
return createStringError(
errc::file_too_large,
"writing section " + Sec.Name + " at offset 0x" +
Twine::utohexstr(Sec.Offset) + " greater than max offset 0x" +
Twine::utohexstr(*MaxSectionOffset) +
" specified by --max-section-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> MaxSectionOffset;

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),
MaxSectionOffset(ELFConfig.MaxSectionOffset) {}
};

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
23 changes: 23 additions & 0 deletions llvm/test/tools/llvm-objcopy/ELF/max-section-offset.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# RUN: yaml2obj %s --docnum=1 -o %t
# RUN: not llvm-objcopy -O binary %t %t2 --max-section-offset=15 2>&1 | FileCheck -DFILE=%t %s --check-prefix=INVALID-COPY
# RUN: llvm-objcopy -O binary %t %t2 --max-section-offset=16

# INVALID-COPY: error: '[[FILE]]': writing section .high_addr at offset 0x10 greater than max offset 0xf specified by --max-section-offset

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Address: 0x0
Content: "10"
- Name: .high_addr
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
Address: 0x10
Content: "10"
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_max_section_offset)) {
ELFConfig.MaxSectionOffset = std::stoull(Arg->getValue());
}

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

defm max_section_offset
: Eq<"max-section-offset",
"Emit an error if input section has a file offset greater than the "
"specified `offset`">,
MetaVarName<"offset">;

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