Patch by Nicholas Allegra.
The Mach-O writer calculates the size of load commands multiple times.
First, Util::assignAddressesToSections() (in MachONormalizedFileFromAtoms.cpp)
calculates the size using headerAndLoadCommandsSize() (in
MachONormalizedFileBinaryWriter.cpp), which creates a temporary
MachOFileLayout for the NormalizedFile, only to retrieve its
headerAndLoadCommandsSize. Later, writeBinary() (in
MachONormalizedFileBinaryWriter.cpp) creates a new layout and uses the offsets
from that layout to actually write out everything in the NormalizedFile.
But the NormalizedFile changes between the first computation and the second.
When Util::assignAddressesToSections is called, file.functionStarts is always
empty because Util::addFunctionStarts has not yet been called. Yet
MachOFileLayout decides whether to include a LC_FUNCTION_STARTS command based
on whether file.functionStarts is nonempty. Therefore, the initial computation
always omits it.
Because padding for the __TEXT segment (to make its size a multiple of the
page size) is added between the load commands and the first section, LLD still
generates a valid binary as long as the amount of padding happens to be large
enough to fit LC_FUNCTION_STARTS command, which it usually is.
However, it's easy to reproduce the issue by adding a section of a precise
size. Given foo.c:
__attribute__((section("__TEXT,__foo")))
char foo[0xd78] = {0};
Run:
clang -dynamiclib -o foo.dylib foo.c -fuse-ld=lld -install_name
/usr/lib/foo.dylib
otool -lvv foo.dylib
This should produce:
truncated or malformed object (offset field of section 1 in LC_SEGMENT_64
command 0 not past the headers of the file)
This commit:
- Changes MachOFileLayout to always assume LC_FUNCTION_STARTS is present for
the initial computation, as long as generating LC_FUNCTION_STARTS is
enabled. It would be slightly better to check whether there are actually
any functions, since no LC_FUNCTION_STARTS will be generated if not, but it
doesn't cause a problem if the initial computation is too high.
- Adds a test.
- Adds an assert in MachOFileLayout::writeSectionContent() that we are not
writing section content into the load commands region (which would happen
if the offset was calculated too low due to the initial load commands size
calculation being too low). Adds an assert in
MachOFileLayout::writeLoadCommands to validate a similar situation where
two size-of-load-commands computations are expected to be equivalent.
llvm-svn: 358545
to reflect the new license.
We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.
Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.
llvm-svn: 351636
New lld's files are spread under lib subdirectory, and it isn't easy
to find which files are actually maintained. This patch moves maintained
files to Common subdirectory.
Differential Revision: https://reviews.llvm.org/D37645
llvm-svn: 314719
This creates a new library called BinaryFormat that has all of
the headers from llvm/Support containing structure and layout
definitions for various types of binary formats like dwarf, coff,
elf, etc as well as the code for identifying a file from its
magic.
Differential Revision: https://reviews.llvm.org/D33843
llvm-svn: 304864
This patch causes LLD to build stabs debugging symbols for files containing
DWARF debug info, and to propagate existing stabs symbols for object files
built using '-r' mode. This enables debugging of binaries generated by LLD
from MachO objects.
llvm-svn: 276921
The .o path always makes sure to store a power of 2 value in the
Section alignment. However, the YAML code didn't verify this.
Added verification and updated all the tests which had a 3 but meant
to have 2^3.
llvm-svn: 264228
Also added the defaults for whether to generate this load command, which
the cmdline options are able to override.
There was also a difference to ld64 which is fixed here in that ld64 will
generate an empty data in code command if requested.
rdar://problem/24472630
llvm-svn: 260191
This load command generates data in the LINKEDIT section which
is a list of ULEB128 delta's to all of the functions in the __text section.
It is then 0 terminated and pointer aligned to pad.
ld64 exposes the -function-starts and no-function-starts cmdline options
to override behaviour from the defaults based on file types.
rdar://problem/24472630
llvm-svn: 260188
The initial segment protection was also being used to set the maximum
segment protection level. Instead, the maximum should be set according
to the architecture we are linking. For example on Mac OS it should be
RWX on most pages, but on iOS is often on R_X.
rdar://problem/24515136
llvm-svn: 259966
In the case where we are emitting to an object file, the platform is
possibly unknown, and the source object files contained load commands
for version min, we can take the maximum of those min versions and
emit in in the output object file.
This test also tests r259739.
llvm-svn: 259742
If the command line contains something like -macosx_version_min and we
don't explicitly disable generation with -no_version_load_command then
we generate the LC_VERSION_MIN command in the output file.
There's a couple of FIXME's in here. These will be handled soon with
more tests but I didn't want to grow this patch any more than it already was.
rdar://problem/24472630
llvm-svn: 259718
The ObjectFileYAML.roundTrip serializes a default-constructed
NormalizedFile to YAML, triggering uninitialized memory reads.
While there use in-class member initializers.
llvm-svn: 240446
The new constructor's type is the same, but this one takes not a log2
value but an alignment value itself, so the meaning is totally differnet.
llvm-svn: 233244
This patch is to make instantiation and conversion to an integer explicit,
so that we can mechanically replace all occurrences of the class with
integer in the next step.
Now get() returns an alignment value rather than its log2 value.
llvm-svn: 233242
This is a second patch for InputGraph cleanup.
Sorry about the size of the patch, but what I did in this
patch is basically moving code from constructor to a new
method, parse(), so the amount of new code is small.
This has no change in functionality.
We've discussed the issue that we have too many classes
to represent a concept of "file". We have File subclasses
that represent files read from disk. In addition to that,
we have bunch of InputElement subclasses (that are part
of InputGraph) that represent command line arguments for
input file names. InputElement is a wrapper for File.
InputElement has parseFile method. The method instantiates
a File. The File's constructor reads a file from disk and
parses that.
Because parseFile method is called from multiple worker
threads, file parsing is processed in parallel. In other
words, one reason why we needed the wrapper classes is
because a File would start reading a file as soon as it
is instantiated.
So, the reason why we have too many classes here is at
least partly because of the design flaw of File class.
Just like threads in a good threading library, we need
to separate instantiation from "start" method, so that
we can instantiate File objects when we need them (which
should be very fast because it involves only one mmap()
and no real file IO) and use them directly instead of
the wrapper classes. Later, we call parse() on each
file in parallel to let them do actual file IO.
In this design, we can eliminate a reason to have the
wrapper classes.
In order to minimize the size of the patch, I didn't go so
far as to replace the wrapper classes with File classes.
The wrapper classes are still there.
In this patch, we call parse() immediately after
instantiating a File, so this really has no change in
functionality. Eventually the call of parse() should be
moved to Driver::link(). That'll be done in another patch.
llvm-svn: 224102
Mach-o does not use a simple SO_NEEDED to track dependent dylibs. Instead,
the linker copies four things from each dylib to each client: the runtime path
(aka "install name"), the build time, current version (dylib build number), and
compatibility version The build time is no longer used (it cause every rebuild
of a dylib to be different). The compatibility version is usually just 1.0
and never changes, or the dylib becomes incompatible.
This patch copies that information into the NormalizedMachO format and
propagates it to clients.
llvm-svn: 222300
mach-o supports "fat" files which are a header/table-of-contents followed by a
concatenation of mach-o files (or archives of mach-o files) built for
different architectures. Previously, the support for fat files was in the
MachOReader, but that only supported fat .o files and dylibs (not archives).
The fix is to put the fat handing into MachOFileNode. That way any input file
kind (including archives) can be fat. MachOFileNode selects the sub-range
of the fat file that matches the arch being linked and creates a MemoryBuffer
for just that subrange.
llvm-svn: 219268
Most of the changes are in the new file ArchHandler_arm64.cpp. But a few
things had to be fixed to support 16KB pages (instead of 4KB) which iOS arm64
requires. In addition the StubInfo struct had to be expanded because
arm64 uses two instruction (ADRP/LDR) to load a global which requires two
relocations. The other mach-o arches just needed one relocation.
llvm-svn: 217469
Mach-O has a "fat" (or "universal") variant where the same contents built for
different architectures are concatenated into one file with a table-of-contents
header at the start. But this leaves a dilemma for the linker - which
architecture to use.
Normally, the linker command line -arch is used to force which slice of any fat
files are used. The clang compiler always passes -arch to the linker when
invoking it. But some Makefiles invoke the linker directly and don’t specify
the -arch option. For those cases, the linker scans all input files in command
line order and finds the first non-fat object file. Whatever architecture it
is becomes the architecture for the link.
llvm-svn: 217189
Sometimes compilers emit data into code sections (e.g. constant pools or
jump tables). These runs of data can throw off disassemblers. The solution
in mach-o is that ranges of data-in-code are encoded into a table pointed to
by the LC_DATA_IN_CODE load command.
The way the data-in-code information is encoded into lld's Atom model is that
that start and end of each data run is marked with a Reference whose offset
is the start/end of the data run. For arm, the switch back to code also marks
whether it is thumb or arm code.
llvm-svn: 213901
The main goal of this patch is to allow "mach-o encoded as yaml" and "native
encoded as yaml" documents to be intermixed. They are distinguished via
yaml tags at the start of the document. This will enable all mach-o test cases
to be written using yaml instead of checking in object files.
The Registry was extend to allow yaml tag handlers to be registered. The
mach-o Reader adds a yaml tag handler for the tag "!mach-o".
Additionally, this patch fixes some buffer ownership issues. When parsing
mach-o binaries, the mach-o atoms can have pointers back into the memory
mapped .o file. But with yaml encoded mach-o, name and content are ephemeral,
so a copyRefs parameter was added to cause the mach-o atoms to make their
own copy.
llvm-svn: 198986
The main changes are in:
include/lld/Core/Reference.h
include/lld/ReaderWriter/Reader.h
Everything else is details to support the main change.
1) Registration based Readers
Previously, lld had a tangled interdependency with all the Readers. It would
have been impossible to make a streamlined linker (say for a JIT) which
just supported one file format and one architecture (no yaml, no archives, etc).
The old model also required a LinkingContext to read an object file, which
would have made .o inspection tools awkward.
The new model is that there is a global Registry object. You programmatically
register the Readers you want with the registry object. Whenever you need to
read/parse a file, you ask the registry to do it, and the registry tries each
registered reader.
For ease of use with the existing lld code base, there is one Registry
object inside the LinkingContext object.
2) Changing kind value to be a tuple
Beside Readers, the registry also keeps track of the mapping for Reference
Kind values to and from strings. Along with that, this patch also fixes
an ambiguity with the previous Reference::Kind values. The problem was that
we wanted to reuse existing relocation type values as Reference::Kind values.
But then how can the YAML write know how to convert a value to a string? The
fix is to change the 32-bit Reference::Kind into a tuple with an 8-bit namespace
(e.g. ELF, COFFF, etc), an 8-bit architecture (e.g. x86_64, PowerPC, etc), and
a 16-bit value. This tuple system allows conversion to and from strings with
no ambiguities.
llvm-svn: 197727
This is the first step in how I plan to get mach-o object files support into
lld. We need to be able to test the mach-o Reader and Write on systems without
a mach-o tools. Therefore, we want to support a textual way (YAML) to represent
mach-o files.
MachONormalizedFile.h defines an in-memory abstraction of the content of mach-o
files. The in-memory data structures are always native endianess and always
use 64-bit sizes. That internal data structure can then be converted to or
from three different formats: 1) yaml (text) encoded mach-o, 2) binary mach-o
files, 3) lld Atoms.
This patch defines the internal model and uses YAML I/O to implement the
conversion to and from the model to yaml. The next patch will implement
the conversion from normalized to binary mach-o.
This patch includes unit tests to validate the yaml conversion APIs.
llvm-svn: 192147