Message ID | 1399537603-6905-2-git-send-email-dougkwan@google.com |
---|---|
State | New |
Headers | show |
On 05/08/2014 10:26 AM, Doug Kwan wrote: > Look at ELF header to determin ABI version on PPC64. This is required > for executing the first instruction correctly. > > Signed-off-by: Doug Kwan <dougkwan@google.com> > --- > include/elf.h | 5 +++++ > linux-user/elfload.c | 17 +++++++++++++++-- > 2 files changed, 20 insertions(+), 2 deletions(-) > > diff --git a/include/elf.h b/include/elf.h > index 1599ab2..b39f5db 100644 > --- a/include/elf.h > +++ b/include/elf.h > @@ -561,6 +561,11 @@ typedef struct { > #define SHF_ALPHA_GPREL 0x10000000 > > > +/* PowerPC specific definitions. */ > + > +/* Processor specific flags for the ELF header e_flags field. */ > +#define EF_PPC64_ABI 3 Please write bitmasks in hex. > + > /* PowerPC relocations defined by the ABIs */ > #define R_PPC_NONE 0 > #define R_PPC_ADDR32 1 /* 32bit absolute address */ > diff --git a/linux-user/elfload.c b/linux-user/elfload.c > index 995f999..b96d64a 100644 > --- a/linux-user/elfload.c > +++ b/linux-user/elfload.c > @@ -777,12 +777,18 @@ static uint32_t get_elf_hwcap(void) > NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ > } while (0) > > +static inline uint32_t get_ppc64_abi(struct image_info *infop); > + > static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) > { > _regs->gpr[1] = infop->start_stack; > #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) > - _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; > - infop->entry = ldq_raw(infop->entry) + infop->load_bias; > + if (get_ppc64_abi(infop) < 2) { > + _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; > + infop->entry = ldq_raw(infop->entry) + infop->load_bias; > + } else { > + _regs->gpr[12] = infop->entry; /* r12 set to global entry address */ Uli, is this correct? Also, why don't w need to adjust for the load_bias with ELFv2 anymore? > + } > #endif > _regs->nip = infop->entry; > } > @@ -1152,6 +1158,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i > > #include "elf.h" > > +#ifdef TARGET_PPC > +static inline uint32_t get_ppc64_abi(struct image_info *infop) > +{ > + return infop->elf_flags & EF_PPC64_ABI; > +} > +#endif I'm not sure this is more readable than doing it inline ... :). Alex
Hi On Thu, May 8, 2014 at 1:36 AM, Alexander Graf <agraf@suse.de> wrote: 3 > > > Please write bitmasks in hex. Will fix. > + >> /* PowerPC relocations defined by the ABIs */ >> #define R_PPC_NONE 0 >> #define R_PPC_ADDR32 1 /* 32bit absolute address */ >> diff --git a/linux-user/elfload.c b/linux-user/elfload.c >> index 995f999..b96d64a 100644 >> --- a/linux-user/elfload.c >> +++ b/linux-user/elfload.c >> @@ -777,12 +777,18 @@ static uint32_t get_elf_hwcap(void) >> NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ >> } while (0) >> +static inline uint32_t get_ppc64_abi(struct image_info *infop); >> + >> static inline void init_thread(struct target_pt_regs *_regs, struct >> image_info *infop) >> { >> _regs->gpr[1] = infop->start_stack; >> #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) >> - _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; >> - infop->entry = ldq_raw(infop->entry) + infop->load_bias; >> + if (get_ppc64_abi(infop) < 2) { >> + _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; >> + infop->entry = ldq_raw(infop->entry) + infop->load_bias; >> + } else { >> + _regs->gpr[12] = infop->entry; /* r12 set to global entry address >> */ >> > > Uli, is this correct? Also, why don't w need to adjust for the load_bias > with ELFv2 anymore? No. This is a bug. It was not caught by testing because load_bias is 0 I guess. > > + } >> #endif >> _regs->nip = infop->entry; >> } >> @@ -1152,6 +1158,13 @@ static inline void init_thread(struct >> target_pt_regs *regs, struct image_info *i >> #include "elf.h" >> +#ifdef TARGET_PPC >> +static inline uint32_t get_ppc64_abi(struct image_info *infop) >> +{ >> + return infop->elf_flags & EF_PPC64_ABI; >> +} >> +#endif >> > > I'm not sure this is more readable than doing it inline ... :). > This is done so because the elf header is not yet included before the callee. To eliminate this I need to move the include before ppc's init_thread. Is that okay? Thanks for the comments. -Doug
On 05/08/2014 10:43 AM, Doug Kwan (關振德) wrote: > Hi > > > On Thu, May 8, 2014 at 1:36 AM, Alexander Graf <agraf@suse.de > <mailto:agraf@suse.de>> wrote: 3 > > > Please write bitmasks in hex. > > Will fix. > > + > /* PowerPC relocations defined by the ABIs */ > #define R_PPC_NONE 0 > #define R_PPC_ADDR32 1 /* 32bit absolute > address */ > diff --git a/linux-user/elfload.c b/linux-user/elfload.c > index 995f999..b96d64a 100644 > --- a/linux-user/elfload.c > +++ b/linux-user/elfload.c > @@ -777,12 +777,18 @@ static uint32_t get_elf_hwcap(void) > NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ > } while (0) > +static inline uint32_t get_ppc64_abi(struct image_info *infop); > + > static inline void init_thread(struct target_pt_regs *_regs, > struct image_info *infop) > { > _regs->gpr[1] = infop->start_stack; > #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) > - _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; > - infop->entry = ldq_raw(infop->entry) + infop->load_bias; > + if (get_ppc64_abi(infop) < 2) { > + _regs->gpr[2] = ldq_raw(infop->entry + 8) + > infop->load_bias; > + infop->entry = ldq_raw(infop->entry) + infop->load_bias; > + } else { > + _regs->gpr[12] = infop->entry; /* r12 set to global > entry address */ > > > Uli, is this correct? Also, why don't w need to adjust for the > load_bias with ELFv2 anymore? > > No. This is a bug. It was not caught by testing because load_bias is > 0 I guess. > > > + } > #endif > _regs->nip = infop->entry; > } > @@ -1152,6 +1158,13 @@ static inline void init_thread(struct > target_pt_regs *regs, struct image_info *i > #include "elf.h" > +#ifdef TARGET_PPC > +static inline uint32_t get_ppc64_abi(struct image_info *infop) > +{ > + return infop->elf_flags & EF_PPC64_ABI; > +} > +#endif > > > I'm not sure this is more readable than doing it inline ... :). > > > This is done so because the elf header is not yet included before the > callee. To eliminate this I need to move the include before ppc's > init_thread. Is that okay? Ah, I see. I don't have strong feelings either way. Riku, what would you prefer? Alex
Doug Kwan (關振德) <dougkwan@google.com> wrote on 08.05.2014 10:43:14: On Thu, May 8, 2014 at 1:36 AM, Alexander Graf <agraf@suse.de> wrote: >> - _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; >> - infop->entry = ldq_raw(infop->entry) + infop->load_bias; >> + if (get_ppc64_abi(infop) < 2) { >> + _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; >> + infop->entry = ldq_raw(infop->entry) + infop->load_bias; >> + } else { >> + _regs->gpr[12] = infop->entry; /* r12 set to global entry address */ >> >> Uli, is this correct? Also, why don't w need to adjust for the >> load_bias with ELFv2 anymore? > > No. This is a bug. It was not caught by testing because load_bias > is 0 I guess. Actually, it looks correct to me. The value of infop->entry itself was presumably already adjusted for the load bias by common code. However, on ELFv1, that value points to the descriptor, but the values we *load* from that descriptor *also* need to be adjusted by the load bias, since the image has not yet been relocated at this stage. With ELFv2, the (already adjusted) infop->entry value points directly to the code, so no further adjustment is required. Bye, Ulrich
diff --git a/include/elf.h b/include/elf.h index 1599ab2..b39f5db 100644 --- a/include/elf.h +++ b/include/elf.h @@ -561,6 +561,11 @@ typedef struct { #define SHF_ALPHA_GPREL 0x10000000 +/* PowerPC specific definitions. */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_PPC64_ABI 3 + /* PowerPC relocations defined by the ABIs */ #define R_PPC_NONE 0 #define R_PPC_ADDR32 1 /* 32bit absolute address */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 995f999..b96d64a 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -777,12 +777,18 @@ static uint32_t get_elf_hwcap(void) NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ } while (0) +static inline uint32_t get_ppc64_abi(struct image_info *infop); + static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) { _regs->gpr[1] = infop->start_stack; #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) - _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; - infop->entry = ldq_raw(infop->entry) + infop->load_bias; + if (get_ppc64_abi(infop) < 2) { + _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; + infop->entry = ldq_raw(infop->entry) + infop->load_bias; + } else { + _regs->gpr[12] = infop->entry; /* r12 set to global entry address */ + } #endif _regs->nip = infop->entry; } @@ -1152,6 +1158,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #include "elf.h" +#ifdef TARGET_PPC +static inline uint32_t get_ppc64_abi(struct image_info *infop) +{ + return infop->elf_flags & EF_PPC64_ABI; +} +#endif + struct exec { unsigned int a_info; /* Use macros N_MAGIC, etc for access */
Look at ELF header to determin ABI version on PPC64. This is required for executing the first instruction correctly. Signed-off-by: Doug Kwan <dougkwan@google.com> --- include/elf.h | 5 +++++ linux-user/elfload.c | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-)