When tokens in macro definitions need cstr_buf inside get_tok_str,
the second might overwrite the first (happens when tokens are
multi-character non-identifiers, see testcase) in macro_is_equal,
failing to diagnose a difference. Use a real local buffer.
Now we can express prefixes with 0x0fxx opcodes we can correct the
movq mem64->xmm opcode, and restrict the movq xmm->mem64 movq to
not invalidly accept mmx.
Disjoint instruction types don't need to be a bit field, so
introduce an enumeration (3 bits). Also the 0x0f prefix can
be expressed by a bit, doesn't need a byte in the opcode field.
That enables to encode further prefixes still in 16 bit.
To not have to touch all insns do some macro fiddling filtering
out a 0x0f byte in the second position.
In particular those that are extensions of existing mmx (or sse1)
instructions by a simple 0x66 prefix. There's one caveat for
x86-64: as we don't yet correctly handle the 0xf3 prefix
the movq mem64->xmm is wrong (tested in asmtest.S). Needs
some refactoring of the instr_type member.
- generate and use SYM@PLT for plt addresses
- get rid of patch_dynsym_undef hack (no idea what it did on FreeBSD)
- use sym_attrs instead of symtab_to_dynsym
- special case for function pointers into .so on i386
- libtcc_test: test tcc_add_symbol with data object
- move target specicic code to *-link.c files
- add R_XXX_RELATIVE (needed for PE)
MSVC does not support array designator so cannot compile source using
relocs_info. This commit replace the relocs_info array into a set of
functions, each returning the value given by a given field of the struct
reloc_info.
Last use for pltoff_addend field of relocs_info array was removed in
commit 25927df3b7. It is now useless so
this commit removes it and all initialization related to it.
i386 target does not have PC relative loads. Its ABI therefore require
ebx register to points to the GOT when executing a PLT entry. This means
that PLT entry cannot be used transparently, the compiler needs to
expect execution of a PLT entry to be able to use one, that is a PLT
entry should only be created if the relocation explicitely asks for it
(eg. R_386_PLT32).
This patch creates a new target macro PCRELATIVE_DLLPLT to indicate
whether a target can do a PC relative load in PLT entry when building a
dynamic library. Executable do not normally pose a problem because they
are loaded at a fixed address and thus the absolute address of GOT can
be used.
Note that in such a case, if the compiler does not use a PLT aware
relocation for external access then the code relocation will fall on the
dynamic loader since there is no PLT entry to relocate too.
C standard specifies that array should be declared with a non null size
or with * for standard array. Declaration of relocs_info in tcc.h was
not respecting this rule. This commit add a R_NUM macro that maps to the
R_<ARCH>_NUM macros and declare relocs_info using it. This commit also
moves all linker-related macros from <arch>-gen.c files to <arch>-link.c
ones.
Static relocation of functions in dynamic libraries must use the PLT
entry as the target. Before this commit, it used to be done in 2 parts
for ARM, with the offset of the PLT entry from the beginning of the PLT
being put in the relocated place in build_got_entries () and then the
address of the PLT being added in relocate_section.
This led to code dealing with reading the offset of a bl instruction in
build_got_entries. Furthermore, the addition of the address of the start
of the PLT was done based on the relocation type which does not convey
whether a PLT entry should be used to reach the symbol.
This commit moves the decision to use the PLT as the target in
relocate_section, therefore having the instruction aware code contained
to the target-specific bit of that function (in <target>-link.c).
Note that relocate_syms is *not* the right place to do this because two
different relocations for the same symbol can make different decision.
This is the case in tcc -run mode where the static and dynamic
relocation are done by tcc.
Storing the PLT entry address in the symbol's st_value field and relying
on the specific relocation type being used for dynamic relocation would
work but the PLT entry address would then appear in the static symbol
table (symtab). This would also make the static symbol table entry
differ from the dynamic symbol table entry.
Change alloc_sym_attr into get_sym_attr and add a parameter to control
whether to allocate a new symattr structure or return NULL if symbol is
not found;
Currently GOT/PLT creation happens in two locations depending on whether
the GOT/PLT [entry] is required by the symbol or the relocation:
- bind_exe_dynsym for relocations to undefined symbol
- build_got_entries/put_got_entry for relocations that require a GOT/PLT
entry
This commit consolidate GOT/PLT creation in build_got_entries by
reducing bind_exe_dynsym's job to create a dynamic symbol for undefined
symbols. build_got_entries then invoke put_got_entry if the symbol being
relocated is undefined or the relocation asks for a PLT or GOT [entry].
put_got_entry is also modified to only export a symbol in the dynamic
symbol table when we are in the case of PLT/GOT [entry] required by the
relocation (since undefined symbol are already exported by
bind_exe_dynsym).
Currently we always build a GOT when we recognize a relocation in
build_got_entries even if the relocation does not require one. In the
same spirit, when the relocation does require one we always create a GOT
entry even if not entry is necessary. This patch restricts the creation
of a GOT and a GOT entry to relocations that needs it, ie:
- do not create a GOT if relocation is not related to GOT and symbol is
not UNDEF
- do not create a GOT entry if relocation only relates to beginning of
GOT
On ARM targets, the jump to ld.so resolution routine is done in PLT0 by
loading the offset to the GOT found in PLT+16 and from there loading the
address in GOT+8 and jumping to it.
Currently tcc starts the first regular PLT entry at PLT+16 which thus
does not contain the offset to the GOT. This commit fixes that.
Note that calls via PLT still worked nonetheless because of some missing
dynamic tag which makes ld.so behaves as if RTLD_BIND_NOW was specified
in the environment for all executable created by tcc.
add_elf_sym is a confusing name because it is not clear what the
function does compared to put_elf_sym. As a matter of fact, put_elf_sym
also adds a symbol in a symbol table. Besides, "add_elf_sym" fails to
convey that the function can be used to update a symbol (for instance
its value). "set_elf_sym" seems like a more appropriate name: it will
set a symbol to a given set of properties (value, size, etc.) and create
a new one if non exist for that name as one would expect.
Do not create a new symbol in add_elf_sym if a symbol with same properties
(value, size, info, etc.) already exists. This prevents symbols from
being exported twice in the dynamic symbol table.
Prior to this patch, an error would only be given when a library has an
unresolved undefined symbol if there is no undefined reference for the
same symbol in the executable itself. This patch changes the logic to
check both that the executable has the symbol in its static symbol table
*and* that it is defined to decide if the error path should be followed.
SHF_GROUP flag set on a section indicates that it is part of a section
group and that if the section is removed, the other sections in the same
group should be removed as well [1]. Since section group are guide for
the linking process, they do not have any meaning after linking has
occured. TCC rightfully [2] discard such sections (by not recognizing the
section type) but keeps the SHF_GROUP flag set on sections that were
part of a section group which confuses binutils (objdump and gdb at
least). Clearing that bit makes objdump and gdb accept binaries created
by TCC.
[1] https://docs.oracle.com/cd/E19683-01/816-1386/chapter7-26/index.html
[2] GNU ld does the same
The problem was with tcctest.c:
unsigned set;
__asm__("btsl %1,%0" : "=m"(set) : "Ir"(20) : "cc");
when with tcc compiled with the HAVE_SELINUX option, run with
tcc -run, it would use large addresses far beyond the 32bits
range when tcc did not use the pc-relative mode for accessing
'set' in global data memory. In fact the assembler did not
know about %rip at all.
Changes:
- memory operands use (%rax) not (%eax)
- conversion from VT_LLOCAL: use type VT_PTR
- support 'k' modifier
- support %rip register
- support X(%rip) pc-relative addresses
The test in tcctest.c is from Michael Matz.