diff options
Diffstat (limited to 'ldso/ldso/c6x/dl-startup.h')
-rw-r--r-- | ldso/ldso/c6x/dl-startup.h | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/ldso/ldso/c6x/dl-startup.h b/ldso/ldso/c6x/dl-startup.h index 70a8b89a7..c83e33cb3 100644 --- a/ldso/ldso/c6x/dl-startup.h +++ b/ldso/ldso/c6x/dl-startup.h @@ -6,10 +6,9 @@ * * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ - #undef DL_START #define DL_START(X) \ -int \ +static void * __attribute_used__ \ _dl_start (unsigned placeholder, \ struct elf32_dsbt_loadmap *dl_boot_progmap, \ struct elf32_dsbt_loadmap *dl_boot_ldsomap, \ @@ -34,7 +33,6 @@ _dl_start (unsigned placeholder, \ * B4 --> executable loadmap address * A6 --> interpreter loadmap address * B6 --> dynamic section address - * B14 --> our DP setup by kernel * * NB: DSBT index is always 0 for the executable * and 1 for the interpreter @@ -44,6 +42,74 @@ __asm__(" .text\n" ".globl _start\n" ".hidden _start\n" "_start:\n" + /* Find interpreter DSBT base in dynamic section */ + " MV .S2 B6,B2\n" + " || ADD .D1X B6,4,A2\n" + " LDW .D2T2 *B2++[2],B0\n" + " || LDW .D1T1 *A2++[2],A0\n" + " MVKL .S2 " __stringify(DT_C6000_DSBT_BASE) ",B7\n" + " MVKH .S2 " __stringify(DT_C6000_DSBT_BASE) ",B7\n" + " NOP\n" + " NOP\n" + /* + * B0 now holds dynamic tag and A0 holds tag value. + * Loop through looking for DSBT base tag + */ + "0:\n" + " [B0] CMPEQ .L2 B0,B7,B1\n" + " || [!B0] MVK .S2 1,B1\n" + " [!B1] BNOP .S1 0b,5\n" + " ||[!B1] LDW .D2T2 *B2++[2],B0\n" + " ||[!B1] LDW .D1T1 *A2++[2],A0\n" + /* + * DSBT base in A0 needs to be relocated. + * Search through our loadmap to find where it got loaded. + * + * struct elf32_dsbt_loadmap { + * Elf32_Half version; + * Elf32_Half nsegs; + * struct { + * Elf32_Addr addr; + * Elf32_Addr p_vaddr; + * Elf32_Word p_memsz; + * } segments[]; + * } + * + */ + " MV .S1 A6,A1\n" + " [!A1] MV .S1X B4,A1\n" + " ADD .D1 A1,2,A3\n" + " LDHU .D1T2 *A3++[1],B0\n" /* nsegs */ + " LDW .D1T1 *A3++[1],A10\n" /* addr */ + " LDW .D1T1 *A3++[1],A11\n" /* p_vaddr */ + " LDW .D1T1 *A3++[1],A12\n" /* p_memsz */ + " NOP\n" + " NOP\n" + /* + * Here we have: + * B0 -> number of segments to search. + * A3 -> pointer to next segment to check + * A10 -> segment load address + * A11 -> ELF segment virt address + * A12 -> ELF segment size + */ + "0:\n" + " [!B0] B .S2 0f\n" + " SUB .D2 B0,1,B0\n" + " CMPLTU .L1 A0,A11,A13\n" + " || SUB .S1 A12,1,A12\n" + " ADD .D1 A11,A12,A12\n" + " CMPGTU .L1 A0,A12,A14\n" + " OR .L1 A13,A14,A2\n" + " [A2] B .S2 0b\n" + " || [!A2] SUB .L1 A0,A11,A0\n" + " [B0] LDW .D1T1 *A3++[1],A10\n" /* addr */ + " || [!A2] ADD .L1 A0,A10,A0\n" + " [B0] LDW .D1T1 *A3++[1],A11\n" /* p_vaddr */ + " [B0] LDW .D1T1 *A3++[1],A12\n" /* p_memsz */ + " MV .S2X A0,B14\n" + " NOP\n" + "0:\n" " B .S2 _dl_start\n" " STW .D2T2 B14, *+B14[1]\n" " ADD .D1X B15,8,A8\n" |