Alien-TinyCC

 view release on metacpan or  search on metacpan

src/Changelog  view on Meta::CPAN

- Asm labels for variables and functions (Thomas Preud'homme)
- STT_GNU_IFUNC (Indirect functions as externals) (Thomas Preud'homme)
- More tests (tests2) (Milutin Jovanovic)

version 0.9.25:

- first support for x86-64 target (Shinichiro Hamaji)
- support µClibc
- split tcc.c into tcc.h libtcc.c tccpp.c tccgen.c tcc.c
- improved preprocess output with linenumbers and spaces preserved
- tcc_relocate now copies code into user buffer
- fix bitfields with non-int types and in unions
- improve ARM cross-compiling (Daniel Glöckner)
- link stabstr sections from multiple objects
- better (still limited) support for multiple TCCStates

version 0.9.24:

- added verbosity levels -v, -vv, -vvv
- Accept standard input as an inputstream (Hanzac Chen)
- Support c89 compilers other than gcc (Hanzac Chen)

src/Changelog  view on Meta::CPAN

  441: Fix LL left shift in libtcc1.c:__shldi3 (grischka)
  440: Pass structures and function ptrs through ?: (grischka)
  439: Keep rvalue in bit assignment (bit2 = bit1 = x) (grischka)
  438: Degrade nonportable pointer assignment to warning (grischka)
  437: Call 'saveregs()' before jumping with logical and/or/not (grischka)
  435: Put local static variables into global memory (grischka)
  432/434: Cast double and ptr to bool (grischka)
  420: Zero pad x87 tenbyte long doubles (Felix Nawothnig)
  417: Make 'sizeof' unsigned (Rob Landley)
  397: Fix save_reg for longlongs (Daniel Glöckner)
  396: Fix "invalid relocation entry" problem on ubuntu - (Bernhard Fischer)

- ignore AS_NEEDED ld command
- mark executable sections as executable when running in memory
- added support for win32 wchar_t (Filip Navara)
- segment override prefix support (Filip Navara)
- normalized slashes in paths (Filip Navara)
- windows style fastcall (Filip Navara)
- support for empty input register section in asm (Filip Navara)
- anonymous union/struct support (Filip Navara)
- fixed parsing of function parameters

src/Changelog  view on Meta::CPAN

  error position display.

version 0.9.12:

- more fixes for || and && handling.
- improved '? :' type handling.
- fixed bound checking generation with structures
- force '#endif' to be in same file as matching '#if'
- #include file optimization with '#ifndef #endif' construct detection
- macro handling optimization
- added tcc_relocate() and tcc_get_symbol() in libtcc.

version 0.9.11:

- stdarg.h fix for double type (thanks to Philippe Ribet).
- correct white space characters and added MSDOS newline support.
- fixed invalid implicit function call type declaration.
- special macros such as __LINE__ are defined if tested with defined().
- fixed '!' operator with relocated address.
- added symbol + offset relocation (fixes some static variable initializers)
- '-l' option can be specified anywhere. '-c' option yields default
  output name. added '-r' option for relocatable output.
- fixed '\nnn' octal parsing.
- fixed local extern variables declarations.

version 0.9.10:

- fixed lvalue type when saved in local stack.
- fixed '#include' syntax when using macros.
- fixed '#line' bug.
- removed size limit on strings. Unified string constants handling
  with variable declarations.
- added correct support for '\xX' in wchar_t strings.
- added support for bound checking in generated executables
- fixed -I include order.
- fixed incorrect function displayed in runtime error.

version 0.9.9:

- fixed preprocessor expression parsing for #if/#elif.
- relocated debug info (.stab section).
- relocated bounds info (.bounds section).
- fixed cast to char of char constants ('\377' is -1 instead of 255)
- fixed implicit cast for unary plus.
- strings and '__func__' have now 'char[]' type instead of 'char *'
  (fixes sizeof() return value).
- added __start_xxx and __stop_xxx symbols in linker.
- better DLL creation support (option -shared begins to work).
- ELF sections and hash tables are resized dynamically.
- executables and DLLs are stripped by default.

version 0.9.8:

src/Changelog  view on Meta::CPAN

 - added ELF file output (only usable for debugging now)
 - added debug symbol generation (STAB format).
 - added integrated runtime error analysis ('-g' option: print clear
   run time error messages instead of "Segmentation fault").
 - added first version of tiny memory and bound checker ('-b' option).

version 0.9.2:

 - even faster parsing.
 - various syntax parsing fixes.
 - fixed external relocation handling for variables or functions pointers.
 - better function pointers type handling.
 - can compile multiple files (-i option).
 - ANSI C bit fields are supported.
 - beginning of float/double/long double support.
 - beginning of long long support.

version 0.9.1:

 - full ISOC99 initializers handling.
 - compound literals.

src/arm-gen.c  view on Meta::CPAN

/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN     8

#define CHAR_IS_UNSIGNED

/******************************************************/
/* ELF defines */

#define EM_TCC_TARGET EM_ARM

/* relocation type for 32 bit data relocation */
#define R_DATA_32   R_ARM_ABS32
#define R_DATA_PTR  R_ARM_ABS32
#define R_JMP_SLOT  R_ARM_JUMP_SLOT
#define R_COPY      R_ARM_COPY

#define ELF_START_ADDR 0x00008000
#define ELF_PAGE_SIZE  0x1000

/******************************************************/
#else /* ! TARGET_DEFS_ONLY */

src/arm-gen.c  view on Meta::CPAN

/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
  int r;
  if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
    uint32_t x;
    /* constant case */
    x=encbranch(ind,ind+vtop->c.ul,0);
    if(x) {
      if (vtop->r & VT_SYM) {
	/* relocation case */
	greloc(cur_text_section, vtop->sym, ind, R_ARM_PC24);
      } else
	put_elf_reloc(symtab_section, cur_text_section, ind, R_ARM_PC24, 0);
      o(x|(is_jmp?0xE0000000:0xE1000000));
    } else {
      if(!is_jmp)
	o(0xE28FE004); // add lr,pc,#4
      o(0xE51FF004);   // ldr pc,[pc,#-4]
      if (vtop->r & VT_SYM)
	greloc(cur_text_section, vtop->sym, ind, R_ARM_ABS32);

src/c67-gen.c  view on Meta::CPAN

#define LDOUBLE_SIZE  12
#define LDOUBLE_ALIGN 4
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN     8

/******************************************************/
/* ELF defines */

#define EM_TCC_TARGET EM_C60

/* relocation type for 32 bit data relocation */
#define R_DATA_32   R_C60_32
#define R_DATA_PTR  R_C60_32
#define R_JMP_SLOT  R_C60_JMP_SLOT
#define R_COPY      R_C60_COPY

#define ELF_START_ADDR 0x00000400
#define ELF_PAGE_SIZE  0x1000

/******************************************************/
#else /* ! TARGET_DEFS_ONLY */

src/c67-gen.c  view on Meta::CPAN

    int n, *ptr;
    while (t) {
	ptr = (int *) (cur_text_section->data + t);
	{
	    Sym *sym;

	    // extract 32 bit address from MVKH/MVKL
	    n = ((*ptr >> 7) & 0xffff);
	    n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;

	    // define a label that will be relocated

	    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
	    greloc(cur_text_section, sym, t, R_C60LO16);
	    greloc(cur_text_section, sym, t + 4, R_C60HI16);

	    // clear out where the pointer was

	    *ptr &= ~(0xffff << 7);
	    *(ptr + 1) &= ~(0xffff << 7);
	}

src/c67-gen.c  view on Meta::CPAN

	      (0 << 0));	//parallel
    } else
	ALWAYS_ASSERT(FALSE);

#ifdef ASSEMBLY_LISTING_C67
    fprintf(f, " %s %d %d %d\n", s, a, b, c);
#endif

}

//r=reg to load, fr=from reg, symbol for relocation, constant

void C67_MVKL(int r, int fc)
{
    C67_asm("MVKL.", fc, r, 0);
}

void C67_MVKH(int r, int fc)
{
    C67_asm("MVKH.", fc, r, 0);
}

src/c67-gen.c  view on Meta::CPAN


/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
    int r;
    Sym *sym;

    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
	/* constant case */
	if (vtop->r & VT_SYM) {
	    /* relocation case */

	    // get add into A0, then start the jump B3

	    greloc(cur_text_section, vtop->sym, ind, R_C60LO16);	// rem the inst need to be patched
	    greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);

	    C67_MVKL(C67_A0, 0);	//r=reg to load, constant
	    C67_MVKH(C67_A0, 0);	//r=reg to load, constant
	    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	//  B.S2x  A0

src/c67-gen.c  view on Meta::CPAN

		// Call, must load return address into B3 during delay slots

		sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address
		greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched
		greloc(cur_text_section, sym, ind + 4, R_C60HI16);
		C67_MVKL(C67_B3, 0);	//r=reg to load, constant
		C67_MVKH(C67_B3, 0);	//r=reg to load, constant
		C67_NOP(3);	// put remaining NOPs
	    }
	} else {
	    /* put an empty PC32 relocation */
	    ALWAYS_ASSERT(FALSE);
	}
    } else {
	/* otherwise, indirect call */
	r = gv(RC_INT);
	C67_IREG_B_REG(0, C67_CREG_ZERO, r);	//  B.S2x  r

	if (is_jmp) {
	    C67_NOP(5);		// simple jump, just put NOP
	} else {

src/c67-gen.c  view on Meta::CPAN

}

/* generate a jump to a fixed address */
void gjmp_addr(int a)
{
    Sym *sym;
    // I guess this routine is used for relative short
    // local jumps, for now just handle it as the general
    // case

    // define a label that will be relocated

    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
    greloc(cur_text_section, sym, ind, R_C60LO16);
    greloc(cur_text_section, sym, ind + 4, R_C60HI16);

    gjmp(0);			// place a zero there later the symbol will be added to it
}

/* generate a test. set 'inv' to invert test. Stack entry is popped */
int gtst(int inv, int t)

src/coff.h  view on Meta::CPAN

        long            f_symptr;       /* file pointer to symtab */
        long            f_nsyms;        /* number of symtab entries */
        unsigned short  f_opthdr;       /* sizeof(optional hdr) */
        unsigned short  f_flags;        /* flags */
        unsigned short  f_TargetID;     /* for C6x = 0x0099 */
        };

/*------------------------------------------------------------------------*/
/*  File header flags                                                     */
/*------------------------------------------------------------------------*/
#define  F_RELFLG   0x01       /* relocation info stripped from file       */
#define  F_EXEC     0x02       /* file is executable (no unresolved refs)  */
#define  F_LNNO     0x04       /* line nunbers stripped from file          */
#define  F_LSYMS    0x08       /* local symbols stripped from file         */
#define  F_GSP10    0x10       /* 34010 version                            */
#define  F_GSP20    0x20       /* 34020 version                            */
#define  F_SWABD    0x40       /* bytes swabbed (in names)                 */
#define  F_AR16WR   0x80       /* byte ordering of an AR16WR (PDP-11)      */
#define  F_LITTLE   0x100      /* byte ordering of an AR32WR (vax)         */
#define  F_BIG      0x200      /* byte ordering of an AR32W (3B, maxi)     */
#define  F_PATCH    0x400      /* contains "patch" list in optional header */

src/coff.h  view on Meta::CPAN


/*------------------------------------------------------------------------*/
/*  SECTION HEADER                                                        */
/*------------------------------------------------------------------------*/
struct scnhdr {
        char            s_name[8];      /* section name */
        long            s_paddr;        /* physical address */
        long            s_vaddr;        /* virtual address */
        long            s_size;         /* section size */
        long            s_scnptr;       /* file ptr to raw data for section */
        long            s_relptr;       /* file ptr to relocation */
        long            s_lnnoptr;      /* file ptr to line numbers */
        unsigned int	s_nreloc;       /* number of relocation entries */
        unsigned int	s_nlnno;        /* number of line number entries */
        unsigned int	s_flags;        /* flags */
		unsigned short	s_reserved;     /* reserved byte */
		unsigned short  s_page;         /* memory page id */
        };

#define SCNHDR  struct scnhdr
#define SCNHSZ  sizeof(SCNHDR)

/*------------------------------------------------------------------------*/

src/coff.h  view on Meta::CPAN

/*------------------------------------------------------------------------*/
/* #define _TEXT    ".text" */
#define _DATA    ".data"
#define _BSS     ".bss"
#define _CINIT   ".cinit"
#define _TV      ".tv"

/*------------------------------------------------------------------------*/
/* The low 4 bits of s_flags is used as a section "type"                  */
/*------------------------------------------------------------------------*/
#define STYP_REG    0x00  /* "regular" : allocated, relocated, loaded */
#define STYP_DSECT  0x01  /* "dummy"   : not allocated, relocated, not loaded */
#define STYP_NOLOAD 0x02  /* "noload"  : allocated, relocated, not loaded */
#define STYP_GROUP  0x04  /* "grouped" : formed of input sections */
#define STYP_PAD    0x08  /* "padding" : not allocated, not relocated, loaded */
#define STYP_COPY   0x10  /* "copy"    : used for C init tables - 
                                                not allocated, relocated,
                                                loaded;  reloc & lineno
                                                entries processed normally */
#define STYP_TEXT   0x20   /* section contains text only */
#define STYP_DATA   0x40   /* section contains data only */
#define STYP_BSS    0x80   /* section contains bss only */

#define STYP_ALIGN  0x100  /* align flag passed by old version assemblers */
#define ALIGN_MASK  0x0F00 /* part of s_flags that is used for align vals */
#define ALIGNSIZE(x) (1 << ((x & ALIGN_MASK) >> 8))


/*------------------------------------------------------------------------*/
/*  RELOCATION ENTRIES                                                    */
/*------------------------------------------------------------------------*/
struct reloc
{
   long            r_vaddr;        /* (virtual) address of reference */
   short           r_symndx;       /* index into symbol table */
   unsigned short  r_disp;         /* additional bits for address calculation */
   unsigned short  r_type;         /* relocation type */
};

#define RELOC   struct reloc
#define RELSZ   10                 /* sizeof(RELOC) */

/*--------------------------------------------------------------------------*/
/*   define all relocation types                                            */
/*--------------------------------------------------------------------------*/

#define R_ABS           0         /* absolute address - no relocation       */
#define R_DIR16         01        /* UNUSED                                 */
#define R_REL16         02        /* UNUSED                                 */
#define R_DIR24         04        /* UNUSED                                 */
#define R_REL24         05        /* 24 bits, direct                        */
#define R_DIR32         06        /* UNUSED                                 */
#define R_RELBYTE      017        /* 8 bits, direct                         */
#define R_RELWORD      020        /* 16 bits, direct                        */
#define R_RELLONG      021        /* 32 bits, direct                        */
#define R_PCRBYTE      022        /* 8 bits, PC-relative                    */
#define R_PCRWORD      023        /* 16 bits, PC-relative                   */

src/coff.h  view on Meta::CPAN

		}               x_fcnary;
		unsigned short  x_regcount;   /* number of registers used by func */
	}       x_sym;
	struct
	{
		char    x_fname[FILNMLEN];
	}       x_file;
	struct
	{
		long    x_scnlen;          /* section length */
		unsigned short  x_nreloc;  /* number of relocation entries */
		unsigned short  x_nlinno;  /* number of line numbers */
	}       x_scn;
};

#define SYMENT  struct syment
#define SYMESZ  18      /* sizeof(SYMENT) */

#define AUXENT  union auxent
#define AUXESZ  18      /* sizeof(AUXENT) */

src/elf.h  view on Meta::CPAN

#define DT_SONAME       14              /* Name of shared object */
#define DT_RPATH        15              /* Library search path */
#define DT_SYMBOLIC     16              /* Start symbol search here */
#define DT_REL          17              /* Address of Rel relocs */
#define DT_RELSZ        18              /* Total size of Rel relocs */
#define DT_RELENT       19              /* Size of one Rel reloc */
#define DT_PLTREL       20              /* Type of reloc in PLT */
#define DT_DEBUG        21              /* For debugging; unspecified */
#define DT_TEXTREL      22              /* Reloc might modify .text */
#define DT_JMPREL       23              /* Address of PLT relocs */
#define DT_BIND_NOW     24              /* Process relocations of object */
#define DT_INIT_ARRAY   25              /* Array with addresses of init fct */
#define DT_FINI_ARRAY   26              /* Array with addresses of fini fct */
#define DT_INIT_ARRAYSZ 27              /* Size in bytes of DT_INIT_ARRAY */
#define DT_FINI_ARRAYSZ 28              /* Size in bytes of DT_FINI_ARRAY */
#define DT_NUM          29              /* Number used */
#define DT_LOOS         0x60000000      /* Start of OS-specific */
#define DT_HIOS         0x6fffffff      /* End of OS-specific */
#define DT_LOPROC       0x70000000      /* Start of processor-specific */
#define DT_HIPROC       0x7fffffff      /* End of processor-specific */
#define DT_PROCNUM      DT_MIPS_NUM     /* Most used by any processor */

src/elf.h  view on Meta::CPAN

#define R_SPARC_LOX10   49              /* Truncated 11 bit complemented */
#define R_SPARC_H44     50              /* Direct high 12 of 44 bit */
#define R_SPARC_M44     51              /* Direct mid 22 of 44 bit */
#define R_SPARC_L44     52              /* Direct low 10 of 44 bit */
#define R_SPARC_REGISTER 53             /* Global register usage */
#define R_SPARC_UA64    54              /* Direct 64 bit unaligned */
#define R_SPARC_UA16    55              /* Direct 16 bit unaligned */
/* Keep this the last entry.  */
#define R_SPARC_NUM     56

/* AMD x86-64 relocations.  */
#define R_X86_64_NONE		0	/* No reloc */
#define R_X86_64_64		1	/* Direct 64 bit  */
#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
#define R_X86_64_PLT32		4	/* 32 bit PLT address */
#define R_X86_64_COPY		5	/* Copy symbol at runtime */
#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
#define R_X86_64_RELATIVE	8	/* Adjust by program base */
#define R_X86_64_GOTPCREL	9	/* 32 bit signed PC relative

src/elf.h  view on Meta::CPAN

#define DT_MIPS_UNREFEXTNO   0x70000012 /* First external DYNSYM */
#define DT_MIPS_GOTSYM       0x70000013 /* First GOT entry in DYNSYM */
#define DT_MIPS_HIPAGENO     0x70000014 /* Number of GOT page table entries */
#define DT_MIPS_RLD_MAP      0x70000016 /* Address of run time loader map.  */
#define DT_MIPS_DELTA_CLASS  0x70000017 /* Delta C++ class definition.  */
#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
                                                DT_MIPS_DELTA_CLASS.  */
#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
                                                DT_MIPS_DELTA_INSTANCE.  */
#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
                                             DT_MIPS_DELTA_RELOC.  */
#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
                                           relocations refer to.  */
#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
                                           DT_MIPS_DELTA_SYM.  */
#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
                                             class declaration.  */
#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
                                                DT_MIPS_DELTA_CLASSSYM.  */
#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
#define DT_MIPS_PIXIE_INIT   0x70000023
#define DT_MIPS_SYMBOL_LIB   0x70000024
#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025

src/elf.h  view on Meta::CPAN

/* Legal values for sh_type field of Elf32_Shdr.  */

#define SHT_PARISC_GOT          0x70000000 /* GOT for external data.  */
#define SHT_PARISC_ARCH         0x70000001 /* Architecture extensions.  */
#define SHT_PARISC_GLOBAL       0x70000002 /* Definition of $global$.  */
#define SHT_PARISC_MILLI        0x70000003 /* Millicode routines.  */
#define SHT_PARISC_UNWIND       0x70000004 /* Unwind information.  */
#define SHT_PARISC_PLT          0x70000005 /* Procedure linkage table.  */
#define SHT_PARISC_SDATA        0x70000006 /* Short initialized data.  */
#define SHT_PARISC_SBSS         0x70000007 /* Short uninitialized data.  */
#define SHT_PARISC_SYMEXTN      0x70000008 /* Argument/relocation info.  */
#define SHT_PARISC_STUBS        0x70000009 /* Linker stubs.  */

/* Legal values for sh_flags field of Elf32_Shdr.  */

#define SHF_PARISC_GLOBAL       0x10000000 /* Section defines dp.  */
#define SHF_PARISC_SHORT        0x20000000 /* Section with short addressing. */

/* Legal values for ST_TYPE subfield of st_info (symbol type).  */

#define STT_PARISC_MILLICODE    13      /* Millicode function entry point.  */

src/elf.h  view on Meta::CPAN

#define R_ALPHA_COPY            24      /* Copy symbol at runtime */
#define R_ALPHA_GLOB_DAT        25      /* Create GOT entry */
#define R_ALPHA_JMP_SLOT        26      /* Create PLT entry */
#define R_ALPHA_RELATIVE        27      /* Adjust by program base */
/* Keep this the last entry.  */
#define R_ALPHA_NUM             28


/* PowerPC specific declarations */

/* PowerPC relocations defined by the ABIs */
#define R_PPC_NONE              0
#define R_PPC_ADDR32            1       /* 32bit absolute address */
#define R_PPC_ADDR24            2       /* 26bit address, 2 bits ignored.  */
#define R_PPC_ADDR16            3       /* 16bit absolute address */
#define R_PPC_ADDR16_LO         4       /* lower 16bit of absolute address */
#define R_PPC_ADDR16_HI         5       /* high 16bit of absolute address */
#define R_PPC_ADDR16_HA         6       /* adjusted high 16bit */
#define R_PPC_ADDR14            7       /* 16bit address, 2 bits ignored */
#define R_PPC_ADDR14_BRTAKEN    8
#define R_PPC_ADDR14_BRNTAKEN   9

src/elf.h  view on Meta::CPAN

#define R_PPC_EMB_SDA2REL       108
#define R_PPC_EMB_SDA21         109     /* 16 bit offset in SDA */
#define R_PPC_EMB_MRKREF        110
#define R_PPC_EMB_RELSEC16      111
#define R_PPC_EMB_RELST_LO      112
#define R_PPC_EMB_RELST_HI      113
#define R_PPC_EMB_RELST_HA      114
#define R_PPC_EMB_BIT_FLD       115
#define R_PPC_EMB_RELSDA        116     /* 16 bit relative offset in SDA */

/* Diab tool relocations.  */
#define R_PPC_DIAB_SDA21_LO     180     /* like EMB_SDA21, but lower 16 bit */
#define R_PPC_DIAB_SDA21_HI     181     /* like EMB_SDA21, but high 16 bit */
#define R_PPC_DIAB_SDA21_HA     182     /* like EMB_SDA21, adjusted high 16 */
#define R_PPC_DIAB_RELSDA_LO    183     /* like EMB_RELSDA, but lower 16 bit */
#define R_PPC_DIAB_RELSDA_HI    184     /* like EMB_RELSDA, but high 16 bit */
#define R_PPC_DIAB_RELSDA_HA    185     /* like EMB_RELSDA, adjusted high 16 */

/* This is a phony reloc to handle any old fashioned TOC16 references
   that may still be in object files.  */
#define R_PPC_TOC16             255

src/i386-asm.c  view on Meta::CPAN

}
#endif

/* XXX: unify with C code output ? */
static void gen_disp32(ExprValue *pe)
{
    Sym *sym = pe->sym;
    if (sym && sym->r == cur_text_section->sh_num) {
        /* same section: we can output an absolute value. Note
           that the TCC compiler behaves differently here because
           it always outputs a relocation to ease (future) code
           elimination in the linker */
        gen_le32(pe->v + sym->jnext - ind - 4);
    } else {
        if (sym && sym->type.t == VT_VOID) {
            sym->type.t = VT_FUNC;
            sym->type.ref = NULL;
        }
        gen_addrpc32(VT_SYM, sym, pe->v);
    }
}

src/i386-asm.c  view on Meta::CPAN

    gen_le16(pe->v);
}
static void gen_disp16(ExprValue *pe)
{
    Sym *sym;
    sym = pe->sym;
    if (sym) {
        if (sym->r == cur_text_section->sh_num) {
            /* same section: we can output an absolute value. Note
               that the TCC compiler behaves differently here because
               it always outputs a relocation to ease (future) code
               elimination in the linker */
            gen_le16(pe->v + sym->jnext - ind - 2);
        } else {
            greloc(cur_text_section, sym, ind, R_386_PC16);
            gen_le16(pe->v - 2);
        }
    } else {
        /* put an empty PC32 relocation */
        put_elf_reloc(symtab_section, cur_text_section,
                      ind, R_386_PC16, 0);
        gen_le16(pe->v - 2);
    }
}
#endif

/* generate the modrm operand */
static inline void asm_modrm(int reg, Operand *op)
{

src/i386-asm.c  view on Meta::CPAN

#ifndef TCC_TARGET_X86_64
    if (pa->opcode == 0x9a || pa->opcode == 0xea) {
        /* ljmp or lcall kludge */
#ifdef I386_ASM_16
        if (s1->seg_size == 16 && o32 == 0)
            gen_expr16(&ops[1].e);
        else
#endif
            gen_expr32(&ops[1].e);
        if (ops[0].e.sym)
            tcc_error("cannot relocate");
        gen_le16(ops[0].e.v);
        return;
    }
#endif
    for(i = 0;i < nb_ops; i++) {
        v = op_type[i];
        if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64 | OP_IM8S | OP_ADDR)) {
            /* if multiple sizes are given it means we must look
               at the op size */
            if ((v | OP_IM8 | OP_IM64) == (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64)) {

src/i386-asm.c  view on Meta::CPAN

                    v = OP_IM8;
                else if (s == 1)
                    v = OP_IM16;
                else if (s == 2 || (v & OP_IM64) == 0)
                    v = OP_IM32;
                else
                    v = OP_IM64;
            }
            if (v & (OP_IM8 | OP_IM8S)) {
                if (ops[i].e.sym)
                    goto error_relocate;
                g(ops[i].e.v);
            } else if (v & OP_IM16) {
#ifdef I386_ASM_16
                if (s1->seg_size == 16)
                    gen_expr16(&ops[i].e);
                else
#endif
                if (ops[i].e.sym)
                error_relocate:
                    tcc_error("cannot relocate");
                else
                    gen_le16(ops[i].e.v);
            } else {
                if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
                    if (is_short_jmp)
                        g(ops[i].e.v);
#ifdef I386_ASM_16
                    else if (s1->seg_size == 16)
                        gen_disp16(&ops[i].e);
#endif

src/i386-gen.c  view on Meta::CPAN

#define MAX_ALIGN     8


#define psym oad

/******************************************************/
/* ELF defines */

#define EM_TCC_TARGET EM_386

/* relocation type for 32 bit data relocation */
#define R_DATA_32   R_386_32
#define R_DATA_PTR  R_386_32
#define R_JMP_SLOT  R_386_JMP_SLOT
#define R_COPY      R_386_COPY

#define ELF_START_ADDR 0x08048000
#define ELF_PAGE_SIZE  0x1000

/******************************************************/
#else /* ! TARGET_DEFS_ONLY */

src/i386-gen.c  view on Meta::CPAN

    o(c);
    ind1 = ind + 4;
    if (ind1 > cur_text_section->data_allocated)
        section_realloc(cur_text_section, ind1);
    *(int *)(cur_text_section->data + ind) = s;
    s = ind;
    ind = ind1;
    return s;
}

/* output constant with relocation if 'r & VT_SYM' is true */
ST_FUNC void gen_addr32(int r, Sym *sym, int c)
{
    if (r & VT_SYM)
        greloc(cur_text_section, sym, ind, R_386_32);
    gen_le32(c);
}

ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
{
    if (r & VT_SYM)

src/i386-gen.c  view on Meta::CPAN

    greloc(cur_text_section, sym, ind-4, R_386_PC32);
}

/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
    int r;
    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
        /* constant case */
        if (vtop->r & VT_SYM) {
            /* relocation case */
            greloc(cur_text_section, vtop->sym, 
                   ind + 1, R_386_PC32);
        } else {
            /* put an empty PC32 relocation */
            put_elf_reloc(symtab_section, cur_text_section, 
                          ind + 1, R_386_PC32, 0);
        }
        oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
    } else {
        /* otherwise, indirect call */
        r = gv(RC_INT);
        o(0xff); /* call/jmp *r */
        o(0xd0 + r + (is_jmp << 4));
    }

src/i386-gen.c  view on Meta::CPAN

    case  4: func = TOK___bound_ptr_indir4; break;
    case  8: func = TOK___bound_ptr_indir8; break;
    case 12: func = TOK___bound_ptr_indir12; break;
    case 16: func = TOK___bound_ptr_indir16; break;
    default:
        tcc_error("unhandled size when dereferencing bounded pointer");
        func = 0;
        break;
    }

    /* patch relocation */
    /* XXX: find a better solution ? */
    rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul);
    sym = external_global_sym(func, &func_old_type, 0);
    if (!sym->c)
        put_extern_sym(sym, NULL, 0, 0);
    rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info));
}
#endif

/* Save the stack pointer onto the stack */

src/il-gen.c  view on Meta::CPAN

        goto no_var;
    }
    if (varstr) {
        pstrcat(buf, buf_size, " ");
        pstrcat(buf, buf_size, varstr);
    }
 no_var: ;
}


/* patch relocation entry with value 'val' */
void greloc_patch1(Reloc *p, int val)
{
}

/* output a symbol and patch all calls to it */
void gsym_addr(t, a)
{
}

/* output jump and return symbol */

src/libtcc.c  view on Meta::CPAN

        esym->st_shndx = sh_num;
    }
}

ST_FUNC void put_extern_sym(Sym *sym, Section *section, 
                           addr_t value, unsigned long size)
{
    put_extern_sym2(sym, section, value, size, 1);
}

/* add a new relocation entry to symbol 'sym' in section 's' */
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
{
    int c = 0;
    if (sym) {
        if (0 == sym->c)
            put_extern_sym(sym, NULL, 0, 0);
        c = sym->c;
    }
    /* now we can add ELF relocation info */
    put_elf_reloc(symtab_section, s, offset, type, c);
}

/********************************************************/

static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
{
    int len;
    len = strlen(buf);
    vsnprintf(buf + len, buf_size - len, fmt, ap);

src/libtcc.h  view on Meta::CPAN

/* equivalent to -Lpath option */
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);

/* the library name is the same as the argument of the '-l' option */
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);

/* add a symbol to the compiled program */
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);

/* output an executable, library or object file. DO NOT call
   tcc_relocate() before. */
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);

/* link and run main() function and return its value. DO NOT call
   tcc_relocate() before. */
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);

/* do all relocations (needed before using tcc_get_symbol()) */
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
/* possible values for 'ptr':
   - TCC_RELOCATE_AUTO : Allocate and manage memory internally
   - NULL              : return required memory size for the step below
   - memory address    : copy code to memory passed by the caller
   returns -1 if error. */
#define TCC_RELOCATE_AUTO (void*)1

/* return symbol value or NULL if not found */
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);

src/tcc-doc.texi  view on Meta::CPAN


Currently, MMX opcodes are supported but not SSE ones.

@node linker
@chapter TinyCC Linker
@cindex linker

@section ELF file generation
@cindex ELF

TCC can directly output relocatable ELF files (object files),
executable ELF files and dynamic ELF libraries without relying on an
external linker.

Dynamic ELF libraries can be output but the C compiler does not generate
position independent code (PIC). It means that the dynamic library
code generated by TCC cannot be factorized among processes yet.

TCC linker eliminates unreferenced object code in libraries. A single pass is
done on the object and library list, so the order in which object files and
libraries are specified is important (same constraint as GNU ld). No grouping

src/tcc.c  view on Meta::CPAN

           "  -bench      show compilation statistics\n"
           "Preprocessor options:\n"
           "  -E          preprocess only\n"
           "  -Idir       add include path 'dir'\n"
           "  -Dsym[=val] define 'sym' with value 'val'\n"
           "  -Usym       undefine 'sym'\n"
           "Linker options:\n"
           "  -Ldir       add library path 'dir'\n"
           "  -llib       link with dynamic or static library 'lib'\n"
           "  -pthread    link with -lpthread and -D_REENTRANT (POSIX Linux)\n"
           "  -r          generate (relocatable) object file\n"
           "  -rdynamic   export all global symbols to dynamic linker\n"
           "  -shared     generate a shared library\n"
           "  -soname     set name for shared library to be used at runtime\n"
           "  -static     static linking\n"
           "  -Wl,-opt[=val]  set linker option (see manual)\n"
           "Debugger options:\n"
           "  -g          generate runtime debug info\n"
#ifdef CONFIG_TCC_BCHECK
           "  -b          compile with built-in memory and bounds checker (implies -g)\n"
#endif

src/tcc.h  view on Meta::CPAN

    unsigned char *data;       /* section data */
    unsigned long data_allocated; /* used for realloc() handling */
    int sh_name;             /* elf section name (only used during output) */
    int sh_num;              /* elf section number */
    int sh_type;             /* elf section type */
    int sh_flags;            /* elf section flags */
    int sh_info;             /* elf section info */
    int sh_addralign;        /* elf section alignment */
    int sh_entsize;          /* elf entry size */
    unsigned long sh_size;   /* section size (only used during output) */
    addr_t sh_addr;          /* address at which the section is relocated */
    unsigned long sh_offset; /* file offset */
    int nb_hashed_syms;      /* used to resize the hash table */
    struct Section *link;    /* link to another section */
    struct Section *reloc;   /* corresponding section for relocation, if any */
    struct Section *hash;     /* hash table for symbols */
    struct Section *next;
    char name[1];           /* section name */
} Section;

typedef struct DLLReference {
    int level;
    void *handle;
    char name[1];
} DLLReference;

src/tcc.h  view on Meta::CPAN

    unsigned pe_stack_size;
# ifdef TCC_TARGET_X86_64
    Section *uw_pdata;
    int uw_sym;
    unsigned uw_offs;
# endif
#endif

#ifdef TCC_IS_NATIVE
    const char *runtime_main;
    /* for tcc_relocate */
    void *runtime_mem;
# ifdef HAVE_SELINUX
    void *write_mem;
    unsigned long mem_size;
# endif
# if !defined TCC_TARGET_PE && (defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM)
    /* write PLT and GOT here */
    char *runtime_plt_and_got;
    unsigned runtime_plt_and_got_offset;
#  define TCC_HAS_RUNTIME_PLTGOT

src/tcc.h  view on Meta::CPAN

ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int sh_num, const char *name);
ST_FUNC int find_elf_sym(Section *s, const char *name);
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);

ST_FUNC void put_stabs(const char *str, int type, int other, int desc, unsigned long value);
ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);
ST_FUNC void put_stabn(int type, int other, int desc, int value);
ST_FUNC void put_stabd(int type, int other, int desc);

ST_FUNC void relocate_common_syms(void);
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve);
ST_FUNC void relocate_section(TCCState *s1, Section *s);

ST_FUNC void tcc_add_linker_symbols(TCCState *s1);
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
ST_FUNC int tcc_load_archive(TCCState *s1, int fd);
ST_FUNC void tcc_add_bcheck(TCCState *s1);

ST_FUNC void build_got_entries(TCCState *s1);
ST_FUNC void tcc_add_runtime(TCCState *s1);

ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err);

src/tccasm.c  view on Meta::CPAN


    asm_expr_logic(s1, pe);
    for(;;) {
        op = tok;
        if (op != '+' && op != '-')
            break;
        next();
        asm_expr_logic(s1, &e2);
        if (op == '+') {
            if (pe->sym != NULL && e2.sym != NULL)
                goto cannot_relocate;
            pe->v += e2.v;
            if (pe->sym == NULL && e2.sym != NULL)
                pe->sym = e2.sym;
        } else {
            pe->v -= e2.v;
            /* NOTE: we are less powerful than gas in that case
               because we store only one symbol in the expression */
            if (!pe->sym && !e2.sym) {
                /* OK */
            } else if (pe->sym && !e2.sym) {
                /* OK */
            } else if (pe->sym && e2.sym) {
                if (pe->sym == e2.sym) { 
                    /* OK */
                } else if (pe->sym->r == e2.sym->r && pe->sym->r != 0) {
                    /* we also accept defined symbols in the same section */
                    pe->v += pe->sym->jnext - e2.sym->jnext;
                } else {
                    goto cannot_relocate;
                }
                pe->sym = NULL; /* same symbols can be substracted to NULL */
            } else {
            cannot_relocate:
                tcc_error("invalid operation with label");
            }
        }
    }
}

ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
{
    asm_expr_sum(s1, pe);
}

src/tcccoff.c  view on Meta::CPAN


	    if (CoffTextSectionNo == -1 && tcc_sect == stext)
		CoffTextSectionNo = NSectionsToOutput;	// rem which coff sect number the .text sect is

	    strcpy(coff_sec->s_name, tcc_sect->name);	/* section name */

	    coff_sec->s_paddr = tcc_sect->sh_addr;	/* physical address */
	    coff_sec->s_vaddr = tcc_sect->sh_addr;	/* virtual address */
	    coff_sec->s_size = tcc_sect->data_offset;	/* section size */
	    coff_sec->s_scnptr = 0;	/* file ptr to raw data for section */
	    coff_sec->s_relptr = 0;	/* file ptr to relocation */
	    coff_sec->s_lnnoptr = 0;	/* file ptr to line numbers */
	    coff_sec->s_nreloc = 0;	/* number of relocation entries */
	    coff_sec->s_flags = GetCoffFlags(coff_sec->s_name);	/* flags */
	    coff_sec->s_reserved = 0;	/* reserved byte */
	    coff_sec->s_page = 0;	/* memory page id */

	    file_pointer += sizeof(SCNHDR);
	}
    }

    file_hdr.f_nscns = NSectionsToOutput;	/* number of sections */

src/tcccoff.c  view on Meta::CPAN

	tcc_sect = s1->sections[i];

	if (OutputTheSection(tcc_sect)) {
	    // put raw data
	    coff_sec->s_scnptr = file_pointer;	/* file ptr to raw data for section */
	    file_pointer += coff_sec->s_size;
	}
    }

    // now loop through and determine file pointer locations
    // for the relocation data

    for (i = 1; i < s1->nb_sections; i++) {
	coff_sec = &section_header[i];
	tcc_sect = s1->sections[i];

	if (OutputTheSection(tcc_sect)) {
	    // put relocations data
	    if (coff_sec->s_nreloc > 0) {
		coff_sec->s_relptr = file_pointer;	/* file ptr to relocation */
		file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
	    }
	}
    }

    // now loop through and determine file pointer locations
    // for the line number data

    for (i = 1; i < s1->nb_sections; i++) {
	coff_sec = &section_header[i];

src/tcccoff.c  view on Meta::CPAN

    // write raw data
    for (i = 1; i < s1->nb_sections; i++) {
	coff_sec = &section_header[i];
	tcc_sect = s1->sections[i];

	if (OutputTheSection(tcc_sect)) {
	    fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
	}
    }

    // write relocation data
    for (i = 1; i < s1->nb_sections; i++) {
	coff_sec = &section_header[i];
	tcc_sect = s1->sections[i];

	if (OutputTheSection(tcc_sect)) {
	    // put relocations data
	    if (coff_sec->s_nreloc > 0) {
		fwrite(tcc_sect->reloc,
		       coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
	    }
	}
    }


    // group the symbols in order of filename, func1, func2, etc
    // finally global symbols

src/tccelf.c  view on Meta::CPAN

        }
    } else {
    do_def:
        sym_index = put_elf_sym(s, value, size, 
                                ELFW(ST_INFO)(sym_bind, sym_type), other, 
                                sh_num, name);
    }
    return sym_index;
}

/* put relocation */
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
                          int type, int symbol)
{
    char buf[256];
    Section *sr;
    ElfW_Rel *rel;

    sr = s->reloc;
    if (!sr) {
        /* if no relocation section, create it */
        snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
        /* if the symtab is allocated, then we consider the relocation
           are also */
        sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
        sr->sh_entsize = sizeof(ElfW_Rel);
        sr->link = symtab;
        sr->sh_info = s->sh_num;
        s->reloc = sr;
    }
    rel = section_ptr_add(sr, sizeof(ElfW_Rel));
    rel->r_offset = offset;
    rel->r_info = ELFW(R_INFO)(symbol, type);

src/tccelf.c  view on Meta::CPAN

    put_stabs(NULL, type, other, desc, value);
}

ST_FUNC void put_stabd(int type, int other, int desc)
{
    put_stabs(NULL, type, other, desc, 0);
}

/* In an ELF file symbol table, the local symbols must appear below
   the global and weak ones. Since TCC cannot sort it while generating
   the code, we must do it after. All the relocation tables are also
   modified to take into account the symbol table sorting */
static void sort_syms(TCCState *s1, Section *s)
{
    int *old_to_new_syms;
    ElfW(Sym) *new_syms;
    int nb_syms, i;
    ElfW(Sym) *p, *q;
    ElfW_Rel *rel, *rel_end;
    Section *sr;
    int type, sym_index;

src/tccelf.c  view on Meta::CPAN

            old_to_new_syms[i] = q - new_syms;
            *q++ = *p;
        }
        p++;
    }
    
    /* we copy the new symbols to the old */
    memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
    tcc_free(new_syms);

    /* now we modify all the relocations */
    for(i = 1; i < s1->nb_sections; i++) {
        sr = s1->sections[i];
        if (sr->sh_type == SHT_RELX && sr->link == s) {
            rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
            for(rel = (ElfW_Rel *)sr->data;
                rel < rel_end;
                rel++) {
                sym_index = ELFW(R_SYM)(rel->r_info);
                type = ELFW(R_TYPE)(rel->r_info);
                sym_index = old_to_new_syms[sym_index];
                rel->r_info = ELFW(R_INFO)(sym_index, type);
            }
        }
    }
    
    tcc_free(old_to_new_syms);
}

/* relocate common symbols in the .bss section */
ST_FUNC void relocate_common_syms(void)
{
    ElfW(Sym) *sym, *sym_end;
    unsigned long offset, align;
    
    sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
    for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
        sym < sym_end;
        sym++) {
        if (sym->st_shndx == SHN_COMMON) {
            /* align symbol */

src/tccelf.c  view on Meta::CPAN

            offset = bss_section->data_offset;
            offset = (offset + align - 1) & -align;
            sym->st_value = offset;
            sym->st_shndx = bss_section->sh_num;
            offset += sym->st_size;
            bss_section->data_offset = offset;
        }
    }
}

/* relocate symbol table, resolve undefined symbols if do_resolve is
   true and output error if undefined symbol. */
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
{
    ElfW(Sym) *sym, *esym, *sym_end;
    int sym_bind, sh_num, sym_index;
    const char *name;

    sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
    for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
        sym < sym_end;
        sym++) {
        sh_num = sym->st_shndx;

src/tccelf.c  view on Meta::CPAN

    uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
    s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
    /* ldr pc, [pc, #-4] */
    p[0] = 0xE51FF004;
    p[1] = val;
    return (addr_t)p;
}
#endif
#endif /* def TCC_HAS_RUNTIME_PLTGOT */

/* relocate a given section (CPU dependent) */
ST_FUNC void relocate_section(TCCState *s1, Section *s)
{
    Section *sr;
    ElfW_Rel *rel, *rel_end, *qrel;
    ElfW(Sym) *sym;
    int type, sym_index;
    unsigned char *ptr;
    addr_t val, addr;
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
    int esym_index;
#endif

src/tccelf.c  view on Meta::CPAN

                    break;
                } else {
                    qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
                    qrel++;
                }
            }
            *(int *)ptr += val;
            break;
        case R_386_PC32:
            if (s1->output_type == TCC_OUTPUT_DLL) {
                /* DLL relocation */
                esym_index = s1->symtab_to_dynsym[sym_index];
                if (esym_index) {
                    qrel->r_offset = rel->r_offset;
                    qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
                    qrel++;
                    break;
                }
            }
            *(int *)ptr += val - addr;
            break;

src/tccelf.c  view on Meta::CPAN

                if (s1->output_type == TCC_OUTPUT_MEMORY) {
                    if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
                        if (!(x & 3) || !blx_avail || !is_call) {
                            x += add_jmp_table(s1, val) - val; /* add veneer */
                            is_thumb = 0; /* Veneer uses ARM instructions */
                        }
                }
#endif
                if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
                    if (!(x & 3) || !blx_avail || !is_call)
                        tcc_error("can't relocate value at %x",addr);
                x >>= 2;
                x &= 0xffffff;
                /* Only reached if blx is avail and it is a call */
                if (is_thumb) {
                    x |= h << 24;
                    (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
                }
                (*(int *)ptr) |= x;
            }
            break;
        /* Since these relocations only concern Thumb-2 and blx instruction was
           introduced before Thumb-2, we can assume blx is available and not
           guard its use */
        case R_ARM_THM_CALL:
        case R_ARM_THM_JUMP24:
	    {
                int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
                int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
                Section *plt;

                /* weak reference */

src/tccelf.c  view on Meta::CPAN


                /* Compute final offset */
                if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
                    x -= 4;
                x += val - addr;
                if (!to_thumb && is_call) {
                    blx_bit = 0; /* bl -> blx */
                    x = (x + 3) & -4; /* Compute offset from aligned PC */
                }

                /* Check that relocation is possible
                   * offset must not be out of range
                   * if target is to be entered in arm mode:
                     - bit 1 must not set
                     - instruction must be a call (bl) or a jump to PLT */
                if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
                    if (to_thumb || (val & 2) || (!is_call && !to_plt))
                        tcc_error("can't relocate value at %x",addr);

                /* Compute and store final offset */
                s = (x >> 24) & 1;
                i1 = (x >> 23) & 1;
                i2 = (x >> 22) & 1;
                j1 = s ^ (i1 ^ 1);
                j2 = s ^ (i2 ^ 1);
                imm10 = (x >> 12) & 0x3ff;
                imm11 = (x >> 1) & 0x7ff;
                (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |

src/tccelf.c  view on Meta::CPAN

	    }
            break;
        case R_ARM_PREL31:
            {
                int x;
                x = (*(int *)ptr) & 0x7fffffff;
                (*(int *)ptr) &= 0x80000000;
                x = (x * 2) / 2;
                x += val - addr;
                if((x^(x>>1))&0x40000000)
                    tcc_error("can't relocate value at %x",addr);
                (*(int *)ptr) |= x & 0x7fffffff;
            }
        case R_ARM_ABS32:
            *(int *)ptr += val;
            break;
        case R_ARM_REL32:
            *(int *)ptr += val - addr;
            break;
        case R_ARM_BASE_PREL:
            *(int *)ptr += s1->got->sh_addr - addr;

src/tccelf.c  view on Meta::CPAN

                   now TCC uses R_X86_64_32 even for a 64bit pointer */
                qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
                qrel->r_addend = *(int *)ptr + val;
                qrel++;
            }
            *(int *)ptr += val;
            break;

        case R_X86_64_PC32:
            if (s1->output_type == TCC_OUTPUT_DLL) {
                /* DLL relocation */
                esym_index = s1->symtab_to_dynsym[sym_index];
                if (esym_index) {
                    qrel->r_offset = rel->r_offset;
                    qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
                    qrel->r_addend = *(int *)ptr;
                    qrel++;
                    break;
                }
            }
            /* fall through */

src/tccelf.c  view on Meta::CPAN

            if (diff <= -2147483647 || diff > 2147483647) {
#ifdef TCC_HAS_RUNTIME_PLTGOT
                /* XXX: naive support for over 32bit jump */
                if (s1->output_type == TCC_OUTPUT_MEMORY) {
                    val = (add_jmp_table(s1, val - rel->r_addend) +
                           rel->r_addend);
                    diff = val - addr;
                }
#endif
                if (diff <= -2147483647 || diff > 2147483647) {
                    tcc_error("internal error: relocation failed");
                }
            }
            *(int *)ptr += diff;
        }
            break;
        case R_X86_64_GLOB_DAT:
        case R_X86_64_JUMP_SLOT:
            /* They don't need addend */
            *(int *)ptr = val - rel->r_addend;
            break;

src/tccelf.c  view on Meta::CPAN

            break;
        case R_X86_64_GOT32:
            /* we load the got offset */
            *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
            break;
#else
#error unsupported processor
#endif
        }
    }
    /* if the relocation is allocated, we change its symbol table */
    if (sr->sh_flags & SHF_ALLOC)
        sr->link = s1->dynsym;
}

/* relocate relocation table in 'sr' */
static void relocate_rel(TCCState *s1, Section *sr)
{
    Section *s;
    ElfW_Rel *rel, *rel_end;
    
    s = s1->sections[sr->sh_info];
    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
    for(rel = (ElfW_Rel *)sr->data;
        rel < rel_end;
        rel++) {
        rel->r_offset += s->sh_addr;
    }
}

/* count the number of dynamic relocations so that we can reserve
   their space */
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
{
    ElfW_Rel *rel, *rel_end;
    int sym_index, esym_index, type, count;

    count = 0;
    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
    for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
        sym_index = ELFW(R_SYM)(rel->r_info);

src/tccelf.c  view on Meta::CPAN


            p = section_ptr_add(plt, 16);
            p[0] = 0xff; /* jmp *(got + x) */
            p[1] = modrm;
            put32(p + 2, s1->got->data_offset);
            p[6] = 0x68; /* push $xxx */
            put32(p + 7, (plt->data_offset - 32) >> 1);
            p[11] = 0xe9; /* jmp plt_start */
            put32(p + 12, -(plt->data_offset));

            /* the symbol is modified so that it will be relocated to
               the PLT */
#if !defined(TCC_OUTPUT_DLL_WITH_PLT)
            if (s1->output_type == TCC_OUTPUT_EXE)
#endif
                offset = plt->data_offset - 16;
        }
#elif defined(TCC_TARGET_ARM)
        if (reloc_type == R_ARM_JUMP_SLOT) {
            Section *plt;
            uint8_t *p;

src/tccelf.c  view on Meta::CPAN

                put32(p  , 0x4778); // bx pc
                put32(p+2, 0x46c0); // nop
                p += 4;
            } else
                p = section_ptr_add(plt, 16);
            put32(p  , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
            put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
            put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
            put32(p+12, s1->got->data_offset);

            /* the symbol is modified so that it will be relocated to
               the PLT */
            if (s1->output_type == TCC_OUTPUT_EXE)
                offset = plt->data_offset - 16;
        }
#elif defined(TCC_TARGET_C67)
        tcc_error("C67 got not implemented");
#else
#error unsupported CPU
#endif
        index = put_elf_sym(s1->dynsym, offset, 

src/tccelf.c  view on Meta::CPAN

{
    Section *s;
    ElfW_Rel *rel, *rel_end;
    ElfW(Sym) *sym;
    int i, type, reloc_type, sym_index;

    for(i = 1; i < s1->nb_sections; i++) {
        s = s1->sections[i];
        if (s->sh_type != SHT_RELX)
            continue;
        /* no need to handle got relocations */
        if (s->link != symtab_section)
            continue;
        rel_end = (ElfW_Rel *)(s->data + s->data_offset);
        for(rel = (ElfW_Rel *)s->data;
            rel < rel_end;
            rel++) {
            type = ELFW(R_TYPE)(rel->r_info);
            switch(type) {
#if defined(TCC_TARGET_I386)
            case R_386_GOT32:

src/tccelf.c  view on Meta::CPAN

            fwrite(s->data, 1, size, f);
            offset += size;
        }
    }
}

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#define	HAVE_PHDR	1
#define	EXTRA_RELITEMS	14

/* move the relocation value from .dynsym to .got */
void patch_dynsym_undef(TCCState *s1, Section *s)
{
    uint32_t *gotd = (void *)s1->got->data;
    ElfW(Sym) *sym, *sym_end;

    gotd += 3;	// dummy entries in .got
    /* relocate symbols in .dynsym */
    sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
    for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
	if (sym->st_shndx == SHN_UNDEF) {
	    *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
	    sym->st_value = 0;
	}
    }
}
#else
#define	HAVE_PHDR	0

src/tccelf.c  view on Meta::CPAN

ST_FUNC void fill_got(TCCState *s1)
{
	Section *s;
	ElfW_Rel *rel, *rel_end;
	int i;

	for(i = 1; i < s1->nb_sections; i++) {
		s = s1->sections[i];
		if (s->sh_type != SHT_RELX)
			continue;
		/* no need to handle got relocations */
		if (s->link != symtab_section)
			continue;
		rel_end = (ElfW_Rel *) (s->data + s->data_offset);
		for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
			switch (ELFW(R_TYPE) (rel->r_info)) {
			case R_X86_64_GOT32:
			case R_X86_64_GOTPCREL:
			case R_X86_64_PLT32:
				fill_got_entry(s1, rel);
				break;

src/tccelf.c  view on Meta::CPAN

    }

    phdr = NULL;
    section_order = NULL;
    interp = NULL;
    dynamic = NULL;
    dynstr = NULL; /* avoid warning */
    saved_dynamic_data_offset = 0; /* avoid warning */
    
    if (file_type != TCC_OUTPUT_OBJ) {
        relocate_common_syms();

        tcc_add_linker_symbols(s1);

        if (!s1->static_link) {
            const char *name;
            int sym_index, index;
            ElfW(Sym) *esym, *sym_end;

            if (file_type == TCC_OUTPUT_EXE) {
                char *ptr;

src/tccelf.c  view on Meta::CPAN

            s1->plt = new_section(s1, ".plt", SHT_PROGBITS, 
                                  SHF_ALLOC | SHF_EXECINSTR);
            s1->plt->sh_entsize = 4;

            build_got(s1);

            /* scan for undefined symbols and see if they are in the
               dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
               is found, then we add it in the PLT. If a symbol
               STT_OBJECT is found, we add it in the .bss section with
               a suitable relocation */
            sym_end = (ElfW(Sym) *)(symtab_section->data + 
                                    symtab_section->data_offset);
            if (file_type == TCC_OUTPUT_EXE) {
                for(sym = (ElfW(Sym) *)symtab_section->data + 1; 
                    sym < sym_end;
                    sym++) {
                    if (sym->st_shndx == SHN_UNDEF) {
                        name = symtab_section->link->data + sym->st_name;
                        sym_index = find_elf_sym(s1->dynsymtab_section, name);
                        if (sym_index) {

src/tccelf.c  view on Meta::CPAN

            for(i = 0; i < s1->nb_loaded_dlls; i++) {
                DLLReference *dllref = s1->loaded_dlls[i];
                if (dllref->level == 0)
                    put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
            }

            if (s1->rpath)
                put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));

            /* XXX: currently, since we do not handle PIC code, we
               must relocate the readonly segments */
            if (file_type == TCC_OUTPUT_DLL) {
                if (s1->soname)
                    put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
                put_dt(dynamic, DT_TEXTREL, 0);
            }

            if (s1->symbolic)
                put_dt(dynamic, DT_SYMBOLIC, 0);

            /* add necessary space for other entries */

src/tccelf.c  view on Meta::CPAN

        s->sh_name = put_elf_str(strsec, s->name);
#if 0 /* gr */
        printf("section: f=%08x t=%08x i=%08x %s %s\n", 
               s->sh_flags, 
               s->sh_type, 
               s->sh_info, 
               s->name, 
               s->reloc ? s->reloc->name : "n"
               ); 
#endif
        /* when generating a DLL, we include relocations but we may
           patch them */
        if (file_type == TCC_OUTPUT_DLL && 
            s->sh_type == SHT_RELX && 
            !(s->sh_flags & SHF_ALLOC)) {
            /* //gr: avoid bogus relocs for empty (debug) sections */
            if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
                prepare_dynamic_rel(s1, s);
            else if (s1->do_debug)
                s->sh_size = s->data_offset;
        } else if (s1->do_debug ||

src/tccelf.c  view on Meta::CPAN

            file_offset += (a_offset - p_offset);
        } else {
            if (file_type == TCC_OUTPUT_DLL)
                addr = 0;
            else
                addr = ELF_START_ADDR;
            /* compute address after headers */
            addr += (file_offset & (s1->section_align - 1));
        }
        
        /* dynamic relocation table information, for .dynamic section */
        rel_size = 0;
        rel_addr = 0;

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
        bss_addr = bss_size = 0;
#endif
        /* leave one program header for the program interpreter */
        ph = &phdr[0];
        if (interp)
            ph += 1 + HAVE_PHDR;

        for(j = 0; j < 2; j++) {
            ph->p_type = PT_LOAD;
            if (j == 0)
                ph->p_flags = PF_R | PF_X;
            else
                ph->p_flags = PF_R | PF_W;
            ph->p_align = s1->section_align;
            
            /* we do the following ordering: interp, symbol tables,
               relocations, progbits, nobits */
            /* XXX: do faster and simpler sorting */
            for(k = 0; k < 5; k++) {
                for(i = 1; i < s1->nb_sections; i++) {
                    s = s1->sections[i];
                    /* compute if section should be included */
                    if (j == 0) {
                        if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != 
                            SHF_ALLOC)
                            continue;
                    } else {

src/tccelf.c  view on Meta::CPAN

                    file_offset += (int) ( addr - tmp );
                    s->sh_offset = file_offset;
                    s->sh_addr = addr;
                    
                    /* update program header infos */
                    if (ph->p_offset == 0) {
                        ph->p_offset = file_offset;
                        ph->p_vaddr = addr;
                        ph->p_paddr = ph->p_vaddr;
                    }
                    /* update dynamic relocation infos */
                    if (s->sh_type == SHT_RELX) {
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
                        if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
                            rel_addr = addr;
			    rel_size += s->sh_size;	// XXX only first rel.
			}
                        if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
                            bss_addr = addr;
			    bss_size = s->sh_size;	// XXX only first rel.
			}

src/tccelf.c  view on Meta::CPAN

            ph->p_vaddr = dynamic->sh_addr;
            ph->p_paddr = ph->p_vaddr;
            ph->p_filesz = dynamic->sh_size;
            ph->p_memsz = dynamic->sh_size;
            ph->p_flags = PF_R | PF_W;
            ph->p_align = dynamic->sh_addralign;

            /* put GOT dynamic section address */
            put32(s1->got->data, dynamic->sh_addr);

            /* relocate the PLT */
            if (file_type == TCC_OUTPUT_EXE
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
                || file_type == TCC_OUTPUT_DLL
#endif
                ) {
                uint8_t *p, *p_end;

                p = s1->plt->data;
                p_end = p + s1->plt->data_offset;
                if (p < p_end) {

src/tccelf.c  view on Meta::CPAN

                        p += 16;
                    }
#elif defined(TCC_TARGET_C67)
                    /* XXX: TODO */
#else
#error unsupported CPU
#endif
                }
            }

            /* relocate symbols in .dynsym */
            sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
            for(sym = (ElfW(Sym) *)s1->dynsym->data + 1; 
                sym < sym_end;
                sym++) {
                if (sym->st_shndx == SHN_UNDEF) {
                    /* relocate to the PLT if the symbol corresponds
                       to a PLT entry */
                    if (sym->st_value)
                        sym->st_value += s1->plt->sh_addr;
                } else if (sym->st_shndx < SHN_LORESERVE) {
                    /* do symbol relocation */
                    sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
                }
            }

            /* put dynamic section entries */
            dynamic->data_offset = saved_dynamic_data_offset;
            put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
            put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
            put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
            put_dt(dynamic, DT_STRSZ, dynstr->data_offset);

src/tccelf.c  view on Meta::CPAN

            continue;
        section_order[sh_order_index++] = i;
        
        file_offset = (file_offset + s->sh_addralign - 1) & 
            ~(s->sh_addralign - 1);
        s->sh_offset = file_offset;
        if (s->sh_type != SHT_NOBITS)
            file_offset += s->sh_size;
    }
    
    /* if building executable or DLL, then relocate each section
       except the GOT which is already relocated */
    if (file_type != TCC_OUTPUT_OBJ) {
        relocate_syms(s1, 0);

        if (s1->nb_errors != 0) {
        fail:
            ret = -1;
            goto the_end;
        }

        /* relocate sections */
        /* XXX: ignore sections with allocated relocations ? */
        for(i = 1; i < s1->nb_sections; i++) {
            s = s1->sections[i];
            if (s->reloc && s != s1->got)
                relocate_section(s1, s);
        }

        /* relocate relocation entries if the relocation tables are
           allocated in the executable */
        for(i = 1; i < s1->nb_sections; i++) {
            s = s1->sections[i];
            if ((s->sh_flags & SHF_ALLOC) &&
                s->sh_type == SHT_RELX) {
                relocate_rel(s1, s);
            }
        }

        /* get entry point address */
        if (file_type == TCC_OUTPUT_EXE)
            ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
        else
            ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
    }
    if (file_type == TCC_OUTPUT_EXE && s1->static_link)

src/tccelf.c  view on Meta::CPAN

            unsigned char *ptr;
            lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
            ptr = section_ptr_add(s, size);
            read(fd, ptr, size);
        } else {
            s->data_offset += size;
        }
    next: ;
    }

    /* //gr relocate stab strings */
    if (stab_index && stabstr_index) {
        Stab_Sym *a, *b;
        unsigned o;
        s = sm_table[stab_index].s;
        a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
        b = (Stab_Sym *)(s->data + s->data_offset);
        o = sm_table[stabstr_index].offset;
        while (a < b) 
            a->n_strx += o, a++;
    }

src/tccelf.c  view on Meta::CPAN

    old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));

    sym = symtab + 1;
    for(i = 1; i < nb_syms; i++, sym++) {
        if (sym->st_shndx != SHN_UNDEF &&
            sym->st_shndx < SHN_LORESERVE) {
            sm = &sm_table[sym->st_shndx];
            if (sm->link_once) {
                /* if a symbol is in a link once section, we use the
                   already defined symbol. It is very important to get
                   correct relocations */
                if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
                    name = strtab + sym->st_name;
                    sym_index = find_elf_sym(symtab_section, name);
                    if (sym_index)
                        old_to_new_syms[i] = sym_index;
                }
                continue;
            }
            /* if no corresponding section added, no need to add symbol */
            if (!sm->s)

src/tccelf.c  view on Meta::CPAN

            sym->st_value += sm->offset;
        }
        /* add symbol */
        name = strtab + sym->st_name;
        sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size, 
                                sym->st_info, sym->st_other, 
                                sym->st_shndx, name);
        old_to_new_syms[i] = sym_index;
    }

    /* third pass to patch relocation entries */
    for(i = 1; i < ehdr.e_shnum; i++) {
        s = sm_table[i].s;
        if (!s)
            continue;
        sh = &shdr[i];
        offset = sm_table[i].offset;
        switch(s->sh_type) {
        case SHT_RELX:
            /* take relocation offset information */
            offseti = sm_table[sh->sh_info].offset;
            rel_end = (ElfW_Rel *)(s->data + s->data_offset);
            for(rel = (ElfW_Rel *)(s->data + offset);
                rel < rel_end;
                rel++) {
                int type;
                unsigned sym_index;
                /* convert symbol index */
                type = ELFW(R_TYPE)(rel->r_info);
                sym_index = ELFW(R_SYM)(rel->r_info);

src/tccelf.c  view on Meta::CPAN

                if (sym_index >= nb_syms)
                    goto invalid_reloc;
                sym_index = old_to_new_syms[sym_index];
                /* ignore link_once in rel section. */
                if (!sym_index && !sm->link_once
#ifdef TCC_TARGET_ARM
                    && type != R_ARM_V4BX
#endif
                   ) {
                invalid_reloc:
                    tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
                        i, strsec + sh->sh_name, rel->r_offset);
                    goto fail;
                }
                rel->r_info = ELFW(R_INFO)(sym_index, type);
                /* offset the relocation offset */
                rel->r_offset += offseti;
#ifdef TCC_TARGET_ARM
                /* Jumps and branches from a Thumb code to a PLT entry need
                   special handling since PLT entries are ARM code.
                   Unconditional bl instructions referencing PLT entries are
                   handled by converting these instructions into blx
                   instructions. Other case of instructions referencing a PLT
                   entry require to add a Thumb stub before the PLT entry to
                   switch to ARM mode. We set bit 0 of the got offset of a
                   symbol to indicate such a case. */

src/tccgen.c  view on Meta::CPAN

                    sv.c.ul += 4;
                    store(p->r2, &sv);
                }
#endif
                l = loc;
                saved = 1;
            }
            /* mark that stack entry as being saved on the stack */
            if (p->r & VT_LVAL) {
                /* also clear the bounded flag because the
                   relocation address of the function was stored in
                   p->c.ul */
                p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
            } else {
                p->r = lvalue_type(p->type.t) | VT_LOCAL;
            }
            p->r2 = VT_CONST;
            p->c.ul = l;
        }
    }
}

src/tccgen.c  view on Meta::CPAN

    case EXPR_ANY:
        expr_eq();
        break;
    }
    
    dtype = *type;
    dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */

    if (sec) {
        /* XXX: not portable */
        /* XXX: generate error if incorrect relocation */
        gen_assign_cast(&dtype);
        bt = type->t & VT_BTYPE;
        /* we'll write at most 12 bytes */
        if (c + 12 > sec->data_allocated) {
            section_realloc(sec, c + 12);
        }
        ptr = sec->data + c;
        /* XXX: make code faster ? */
        if (!(type->t & VT_BITFIELD)) {
            bit_pos = 0;

src/tccgen.c  view on Meta::CPAN

            sym = get_sym_ref(type, sec, addr, size);
            cval.ul = 0;
            vsetc(type, VT_CONST | VT_SYM, &cval);
            vtop->sym = sym;
        }
        /* patch symbol weakness */
        if (type->t & VT_WEAK)
            weaken_symbol(sym);
#ifdef CONFIG_TCC_BCHECK
        /* handles bounds now because the symbol must be defined
           before for the relocation */
        if (tcc_state->do_bounds_check) {
            unsigned long *bounds_ptr;

            greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR);
            /* then add global bound info */
            bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
            bounds_ptr[0] = 0; /* relocated */
            bounds_ptr[1] = size;
        }
#endif
    }
    if (has_init || (type->t & VT_VLA)) {
        decl_initializer(type, sec, addr, 1, 0);
        /* restore parse state if needed */
        if (init_str.str) {
            tok_str_free(init_str.str);
            restore_parse_state(&saved_parse_state);

src/tccpe.c  view on Meta::CPAN

    WORD e_cp;            /* Pages in file */
    WORD e_crlc;          /* Relocations */
    WORD e_cparhdr;       /* Size of header in paragraphs */
    WORD e_minalloc;      /* Minimum extra paragraphs needed */
    WORD e_maxalloc;      /* Maximum extra paragraphs needed */
    WORD e_ss;            /* Initial (relative) SS value */
    WORD e_sp;            /* Initial SP value */
    WORD e_csum;          /* Checksum */
    WORD e_ip;            /* Initial IP value */
    WORD e_cs;            /* Initial (relative) CS value */
    WORD e_lfarlc;        /* File address of relocation table */
    WORD e_ovno;          /* Overlay number */
    WORD e_res[4];        /* Reserved words */
    WORD e_oemid;         /* OEM identifier (for e_oeminfo) */
    WORD e_oeminfo;       /* OEM information; e_oemid specific */
    WORD e_res2[10];      /* Reserved words */
    DWORD e_lfanew;        /* File address of new exe header */
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

#define IMAGE_NT_SIGNATURE  0x00004550  /* PE00 */
#define SIZE_OF_NT_SIGNATURE 4

src/tccpe.c  view on Meta::CPAN


    0x0004, /*WORD e_cparhdr;       Size of header in paragraphs */
    0x0000, /*WORD e_minalloc;      Minimum extra paragraphs needed */
    0xFFFF, /*WORD e_maxalloc;      Maximum extra paragraphs needed */
    0x0000, /*WORD e_ss;            Initial (relative) SS value */

    0x00B8, /*WORD e_sp;            Initial SP value */
    0x0000, /*WORD e_csum;          Checksum */
    0x0000, /*WORD e_ip;            Initial IP value */
    0x0000, /*WORD e_cs;            Initial (relative) CS value */
    0x0040, /*WORD e_lfarlc;        File address of relocation table */
    0x0000, /*WORD e_ovno;          Overlay number */
    {0,0,0,0}, /*WORD e_res[4];     Reserved words */
    0x0000, /*WORD e_oemid;         OEM identifier (for e_oeminfo) */
    0x0000, /*WORD e_oeminfo;       OEM information; e_oemid specific */
    {0,0,0,0,0,0,0,0,0,0}, /*WORD e_res2[10];      Reserved words */
    0x00000080  /*DWORD   e_lfanew;        File address of new exe header */
    },{
    /* BYTE dosstub[0x40] */
    /* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */
    0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,

src/tccpe.c  view on Meta::CPAN

    } else {
        fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
        if (pe->s1->verbose)
            printf("<- %s (%d symbols)\n", buf, sym_count);
    }
#endif

    for (ord = 0; ord < sym_count; ++ord)
    {
        p = sorted[ord], sym_index = p->index, name = p->name;
        /* insert actual address later in pe_relocate_rva */
        put_elf_reloc(symtab_section, pe->thunk,
            func_o, R_XXX_RELATIVE, sym_index);
        *(DWORD*)(pe->thunk->data + name_o)
            = pe->thunk->data_offset + rva_base;
        *(WORD*)(pe->thunk->data + ord_o)
            = ord;
        put_elf_str(pe->thunk, name);
        func_o += sizeof (DWORD);
        name_o += sizeof (DWORD);
        ord_o += sizeof (WORD);

src/tccpe.c  view on Meta::CPAN

            );
    }
    pe->s1->verbose = 2;
#endif

    tcc_free(section_order);
    return 0;
}

/* ------------------------------------------------------------- */
static void pe_relocate_rva (struct pe_info *pe, Section *s)
{
    Section *sr = s->reloc;
    ElfW_Rel *rel, *rel_end;
    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
    for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
        if (ELFW(R_TYPE)(rel->r_info) == R_XXX_RELATIVE) {
            int sym_index = ELFW(R_SYM)(rel->r_info);
            DWORD addr = s->sh_addr;
            if (sym_index) {
                ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;

src/tccpe.c  view on Meta::CPAN

    d = pe_add_uwwind_info(s1);
    pd = s1->uw_pdata;
    o = pd->data_offset;
    p = section_ptr_add(pd, sizeof *p);

    /* record this function */
    p->BeginAddress = start;
    p->EndAddress = end;
    p->UnwindData = d;

    /* put relocations on it */
    for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
        put_elf_reloc(symtab_section, pd, o,  R_X86_64_RELATIVE, s1->uw_sym);
}
#endif
/* ------------------------------------------------------------- */
#ifdef TCC_TARGET_X86_64
#define PE_STDSYM(n,s) n
#else
#define PE_STDSYM(n,s) "_" n s
#endif

src/tccpe.c  view on Meta::CPAN

static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{
    const char *start_symbol;
    int pe_type = 0;

    if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
        pe_type = PE_GUI;
    else
    if (TCC_OUTPUT_DLL == s1->output_type) {
        pe_type = PE_DLL;
        /* need this for 'tccelf.c:relocate_section()' */
        s1->output_type = TCC_OUTPUT_EXE;
    }
    else
        pe_type = PE_EXE;

    start_symbol =
        TCC_OUTPUT_MEMORY == s1->output_type
        ? PE_GUI == pe_type ? "__runwinmain" : "_main"
        : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12")
        : PE_GUI == pe_type ? "__winstart" : "__start"

src/tccpe.c  view on Meta::CPAN

    int ret;
    struct pe_info pe;
    int i;

    memset(&pe, 0, sizeof pe);
    pe.filename = filename;
    pe.s1 = s1;

    tcc_add_bcheck(s1);
    pe_add_runtime(s1, &pe);
    relocate_common_syms(); /* assign bss adresses */
    tcc_add_linker_symbols(s1);

    ret = pe_check_symbols(&pe);
    if (ret)
        ;
    else if (filename) {
        if (PE_DLL == pe.type) {
            pe.reloc = new_section(pe.s1, ".reloc", SHT_PROGBITS, 0);
            /* XXX: check if is correct for arm-pe target */
            pe.imagebase = 0x10000000;

src/tccpe.c  view on Meta::CPAN

        if (s1->pe_file_align != 0)
            pe.file_align = s1->pe_file_align;

        if ((pe.subsystem >= 10) && (pe.subsystem <= 12))
            pe.imagebase = 0;

        if (s1->has_text_addr)
            pe.imagebase = s1->text_addr;

        pe_assign_addresses(&pe);
        relocate_syms(s1, 0);
        for (i = 1; i < s1->nb_sections; ++i) {
            Section *s = s1->sections[i];
            if (s->reloc) {
                relocate_section(s1, s);
                pe_relocate_rva(&pe, s);
            }
        }
        if (s1->nb_errors)
            ret = -1;
        else
            ret = pe_write(&pe);
        tcc_free(pe.sec_info);
    } else {
#ifdef TCC_IS_NATIVE
        pe.thunk = data_section;

src/tccrun.c  view on Meta::CPAN

#endif

#ifdef _WIN32
#define ucontext_t CONTEXT
#endif

static void set_pages_executable(void *ptr, unsigned long length);
static void set_exception_handler(void);
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level);
static void rt_error(ucontext_t *uc, const char *fmt, ...);
static int tcc_relocate_ex(TCCState *s1, void *ptr);

#ifdef _WIN64
static void win64_add_function_table(TCCState *s1);
#endif

/* ------------------------------------------------------------- */
/* Do all relocations (needed before using tcc_get_symbol())
   Returns -1 on error. */

LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
{
    int ret;

    if (TCC_RELOCATE_AUTO != ptr)
        return tcc_relocate_ex(s1, ptr);

    ret = tcc_relocate_ex(s1, NULL);
    if (ret < 0)
        return ret;

#ifdef HAVE_SELINUX
    {   /* Use mmap instead of malloc for Selinux.  Ref:
           http://www.gnu.org/s/libc/manual/html_node/File-Size.html */

        char tmpfname[] = "/tmp/.tccrunXXXXXX";
        int fd = mkstemp (tmpfname);

src/tccrun.c  view on Meta::CPAN

        s1->write_mem = mmap (NULL, ret, PROT_READ|PROT_WRITE,
            MAP_SHARED, fd, 0);
        if (s1->write_mem == MAP_FAILED)
            tcc_error("/tmp not writeable");

        s1->runtime_mem = mmap (NULL, ret, PROT_READ|PROT_EXEC,
            MAP_SHARED, fd, 0);
        if (s1->runtime_mem == MAP_FAILED)
            tcc_error("/tmp not executable");

        ret = tcc_relocate_ex(s1, s1->write_mem);
    }
#else
    s1->runtime_mem = tcc_malloc(ret);
    ret = tcc_relocate_ex(s1, s1->runtime_mem);
#endif
    return ret;
}

/* launch the compiled program with the given arguments */
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
{
    int (*prog_main)(int, char **);
    int ret;

    if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
        return -1;

    prog_main = tcc_get_symbol_err(s1, s1->runtime_main);

#ifdef CONFIG_TCC_BACKTRACE
    if (s1->do_debug) {
        set_exception_handler();
        rt_prog_main = prog_main;
    }
#endif

src/tccrun.c  view on Meta::CPAN

        bound_exit = tcc_get_symbol_err(s1, "__bound_exit");
        bound_init();
        ret = (*prog_main)(argc, argv);
        bound_exit();
    } else
#endif
        ret = (*prog_main)(argc, argv);
    return ret;
}

/* relocate code. Return -1 on error, required size if ptr is NULL,
   otherwise copy code into buffer passed by the caller */
static int tcc_relocate_ex(TCCState *s1, void *ptr)
{
    Section *s;
    unsigned long offset, length;
    addr_t mem;
    int i;

    if (NULL == ptr) {
        s1->nb_errors = 0;
#ifdef TCC_TARGET_PE
        pe_output_file(s1, NULL);
#else
        tcc_add_runtime(s1);
        relocate_common_syms();
        tcc_add_linker_symbols(s1);
        build_got_entries(s1);
#endif
        if (s1->nb_errors)
            return -1;
    }

    offset = 0, mem = (addr_t)ptr;
    for(i = 1; i < s1->nb_sections; i++) {
        s = s1->sections[i];
        if (0 == (s->sh_flags & SHF_ALLOC))
            continue;
        length = s->data_offset;
        s->sh_addr = mem ? (mem + offset + 15) & ~15 : 0;
        offset = (offset + length + 15) & ~15;
    }
    offset += 16;

    /* relocate symbols */
    relocate_syms(s1, 1);
    if (s1->nb_errors)
        return -1;

#ifdef TCC_HAS_RUNTIME_PLTGOT
    s1->runtime_plt_and_got_offset = 0;
    s1->runtime_plt_and_got = (char *)(mem + offset);
    /* double the size of the buffer for got and plt entries
       XXX: calculate exact size for them? */
    offset *= 2;
#endif

    if (0 == mem)
        return offset;

    /* relocate each section */
    for(i = 1; i < s1->nb_sections; i++) {
        s = s1->sections[i];
        if (s->reloc)
            relocate_section(s1, s);
    }

    for(i = 1; i < s1->nb_sections; i++) {
        s = s1->sections[i];
        if (0 == (s->sh_flags & SHF_ALLOC))
            continue;
        length = s->data_offset;
        // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
        ptr = (void*)s->sh_addr;
        if (NULL == s->data || s->sh_type == SHT_NOBITS)

src/x86_64-gen.c  view on Meta::CPAN

#define LDOUBLE_SIZE  16
#define LDOUBLE_ALIGN 16
/* maximum alignment (for aligned attribute support) */
#define MAX_ALIGN     16

/******************************************************/
/* ELF defines */

#define EM_TCC_TARGET EM_X86_64

/* relocation type for 32 bit data relocation */
#define R_DATA_32   R_X86_64_32
#define R_DATA_PTR  R_X86_64_64
#define R_JMP_SLOT  R_X86_64_JUMP_SLOT
#define R_COPY      R_X86_64_COPY

#define ELF_START_ADDR 0x08048000
#define ELF_PAGE_SIZE  0x1000

/******************************************************/
#else /* ! TARGET_DEFS_ONLY */

src/x86_64-gen.c  view on Meta::CPAN

    return s;
}

ST_FUNC void gen_addr32(int r, Sym *sym, int c)
{
    if (r & VT_SYM)
        greloc(cur_text_section, sym, ind, R_X86_64_32);
    gen_le32(c);
}

/* output constant with relocation if 'r & VT_SYM' is true */
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
{
    if (r & VT_SYM)
        greloc(cur_text_section, sym, ind, R_X86_64_64);
    gen_le64(c);
}

/* output constant with relocation if 'r & VT_SYM' is true */
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
{
    if (r & VT_SYM)
        greloc(cur_text_section, sym, ind, R_X86_64_PC32);
    gen_le32(c-4);
}

/* output got address with relocation */
static void gen_gotpcrel(int r, Sym *sym, int c)
{
#ifndef TCC_TARGET_PE
    Section *sr;
    ElfW(Rela) *rel;
    greloc(cur_text_section, sym, ind, R_X86_64_GOTPCREL);
    sr = cur_text_section->reloc;
    rel = (ElfW(Rela) *)(sr->data + sr->data_offset - sizeof(ElfW(Rela)));
    rel->r_addend = -4;
#else

src/x86_64-gen.c  view on Meta::CPAN

    }
}

/* 'is_jmp' is '1' if it is a jump */
static void gcall_or_jmp(int is_jmp)
{
    int r;
    if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
        /* constant case */
        if (vtop->r & VT_SYM) {
            /* relocation case */
            greloc(cur_text_section, vtop->sym,
                   ind + 1, R_X86_64_PC32);
        } else {
            /* put an empty PC32 relocation */
            put_elf_reloc(symtab_section, cur_text_section,
                          ind + 1, R_X86_64_PC32, 0);
        }
        oad(0xe8 + is_jmp, vtop->c.ul - 4); /* call/jmp im */
    } else {
        /* otherwise, indirect call */
        r = TREG_R11;
        load(r, vtop);
        o(0x41); /* REX */
        o(0xff); /* call/jmp *r */



( run in 1.967 second using v1.01-cache-2.11-cpan-5511b514fd6 )