[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gcl-devel] Re: [Axiom-developer] Axiom ia64

From: Camm Maguire
Subject: [Gcl-devel] Re: [Axiom-developer] Axiom ia64
Date: 05 Dec 2006 19:15:05 -0500
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2

Greetings, and thanks so much for looking into this!

Richard Harke <address@hidden> writes:

> On Tue November 14 2006 18:43, you wrote:
> > This would be most appreciated, and I'd be happy to lend assistance.
> > Knowledge of the ia64 reloc definitions is obviously key, though I put
> > together the alpha version mostly as a guesswork based on the mips
> > example.  If ia64 were done, we could also share with the lush
> > project, on which the original sfaslbfd_mips was inspired.  And
> > someday it would be great to get this back into bfd upstream.
> >
> > The basic idea is that each section of the .o file has a got table
> > appended to handle the relocs that refer to the special gp register
> > value.
> I have been studying ld.so and also Xorg as that has a loader function.
> Its not clear to me that they handle just the same set of relocs.
> The R_IA64_ defines in elf.h have two bit fields for the ia64 and
> these are used in ld.so but that info seems not to be used in Xorg.
> And bfd uses an enum so such structuring of the values isn't
> possible.
> I notice some comments about a standalone version of the loader
> code. That should be very helpful if it works.

It might -- haven't tried it in a while.  I will do so if you still
need it after the following.

> You said something about the heap having to do with the dlopen version
> not working but I noticed some things that made me think that
> dynamic linking, ie letting the lisp code access vars by name
> was an issue. Can you provide more detail?
> Any suggestions would be helpful.

The standard ia64 build uses dlopen somewhat successfully.  In
addition to limiting the number of loads to ~ 1024, another weakness
stems from the typical usage of loading a .o file into an image,
dumping the image with unexec, and reexecuting later where we left
off.  Many lisp programs are built using this paradigm.  dlopen does
not allow a fixed address to be assigned to the relocated functions
across multiple image executions, and so foils GCL's very fast
function calling mechanism.  This essentially means that either all
loads must be redone on image startup, or the image needs to be
written by a special call to ld via compiler::link, in which the .o
files are relocated and initialized a second time 'by hand'.  This
will probably be clearer if you examine how axiom is built on this
platform in contrast with say x86.

I think the way to start would be to look at a compiled .o file on

address@hidden:~/hol88-2.02.19940316/lisp$ objdump -r hol-writ.o

hol-writ.o:     file format elf64-ia64-little

OFFSET           TYPE              VALUE 
0000000000000010 LTOFF22X          .data.rel.local
0000000000000020 LDXMOV            .data.rel.local
0000000000000022 PCREL21B          do_init
0000000000000051 LTOFF22X          vs_base
0000000000000052 LTOFF22X          vs_top
0000000000000060 LTOFF22X          vs_limit
0000000000000062 LTOFF22X          small_fixnum_table+0x0000000000004000
0000000000000070 LDXMOV            vs_base
0000000000000071 LDXMOV            vs_top
0000000000000080 LTOFF22X          Cnil_body
0000000000000081 LDXMOV            vs_limit
0000000000000090 LDXMOV            small_fixnum_table+0x0000000000004000
00000000000000b0 LDXMOV            Cnil_body
00000000000000c1 GPREL22           .sdata+0x0000000000000228
0000000000000150 GPREL22           .sdata+0x0000000000000230
0000000000000161 GPREL22           .sdata+0x0000000000000238
0000000000000162 LTOFF22X          Ct_body
0000000000000191 LDXMOV            Ct_body
0000000000000240 LTOFF22X          .data.rel.local
0000000000000241 GPREL22           .sdata+0x00000000000001e8
0000000000000242 GPREL22           .sdata+0x00000000000001d8
0000000000000252 GPREL22           .sdata
0000000000000261 LDXMOV            .data.rel.local
0000000000000282 GPREL22           .sdata+0x0000000000000010
0000000000000442 GPREL22           .sdata+0x0000000000000008
00000000000004d1 GPREL22           .sdata+0x00000000000001e0
0000000000000601 GPREL22           .sdata+0x00000000000001f8
0000000000000652 PCREL21B          vs_overflow
0000000000000670 LTOFF22X          small_fixnum_table+0x0000000000004000
0000000000000671 GPREL22           .sdata+0x0000000000000228
0000000000000681 LTOFF22X          Cnil_body
0000000000000691 LDXMOV            small_fixnum_table+0x0000000000004000
00000000000006b0 LDXMOV            Cnil_body
0000000000000700 LTOFF22X          .data.rel.local
0000000000000701 GPREL22           .sdata+0x00000000000001e0
0000000000000702 GPREL22           .sdata+0x0000000000000230
0000000000000710 GPREL22           .sdata+0x0000000000000238
0000000000000711 LTOFF22X          Ct_body
0000000000000720 LDXMOV            .data.rel.local
0000000000000731 LDXMOV            Ct_body
0000000000000851 GPREL22           .sdata+0x00000000000001f8
00000000000008a1 LTOFF22X          .data.rel.local
00000000000008a2 GPREL22           .sdata+0x00000000000001e8
00000000000008b2 GPREL22           .sdata+0x00000000000001d8
00000000000008c0 LDXMOV            .data.rel.local
00000000000008e1 GPREL22           .sdata+0x0000000000000008
0000000000000971 LTOFF22X          vs_base
0000000000000980 LTOFF22X          vs_top
0000000000000981 LTOFF22X          vs_limit
0000000000000990 LDXMOV            vs_base
0000000000000991 LDXMOV            vs_top
00000000000009a0 LDXMOV            vs_limit
00000000000009d0 GPREL22           .sdata+0x0000000000000248
0000000000000a72 PCREL21B          vs_overflow
0000000000000a92 GPREL22           .sdata+0x0000000000000248
0000000000000b21 LTOFF22X          vs_top
0000000000000b30 LTOFF22X          vs_limit
0000000000000b31 LTOFF22X          vs_base
0000000000000b40 LDXMOV            vs_top
0000000000000b41 LDXMOV            vs_limit
0000000000000b50 LDXMOV            vs_base
0000000000000b70 LTOFF22X          .data.rel.local
0000000000000b80 LDXMOV            .data.rel.local
0000000000000be0 LTOFF22X          Cnil_body


We just have a handful of relocs that need handling in practice, and
of these, several are probably already correctly handled by
bfd_get_relocated_section_contents.  Typically, the ones that aren't
are those referring to the gp register, which in this case appears to
be GPREL22, to my untutored guess. These relocs should be handled in
analogy with the GP relocs in sfasl_alpha.c -- i.e. they are rewritten
to refer to a special .got table that is constructed at the end of
each loaded section.  They key functions are alphaelf_create_got and
alphaelf_fix_relocs, the comments to which are somwhat useful:

static asection *
alphaelf_create_got(bfd *b,asymbol **syms,
                   alphaelf_got_info *info) {

  bfd_vma offset;
  asection *p;
  int i;

  /* Check that there are no GOT section */
  info->sgot = bfd_get_section_by_name(b, ".got");
  /* Compute GOT hash table */
  offset = 0;
  for (p=b->sections; p; p=p->next)
    if ((p->flags & SEC_ALLOC) && (p->flags & SEC_RELOC)) {
      int sz,reloc_count;
      arelent **reloc;
      /*  ALPHA native relocs: This section and analogs below have
          been modified to avoid orelocation in favor of relocation
          itself.  bfd_canonicalize_reloc reads in the relocation
          table to the latter as an array and makes a pointer list
          to it in the supplied argument.  We will call
          bfd_get_relocated_section_contents, which will call
          bfd_canonicalize_reloc internally, on all sections,
          including the new .got section.  If no relocation array
          exists, this will fail when bfd_cannicalize_reloc attempts
          to read in the non-existent table.  20050409 CM*/
      sz = bfd_get_reloc_upper_bound(b, p);
      reloc_count = bfd_canonicalize_reloc(b, p, reloc, syms);
      assert(p->reloc_count==0 || p->reloc_count==reloc_count);
      for (i=0; i<p->reloc_count; i++) {
        arelent *reloc = p->relocation+i;
        if ((reloc->howto==info->reloc_literal)) {
          const char *name = msymbol_name(b,*reloc->sym_ptr_ptr,reloc->addend);
          alphaelf_got_entry *gotent = (alphaelf_got_entry*)
            bfd_hash_lookup(&info->got_table, name, TRUE, TRUE );
          if (!gotent->reloc) {
            gotent->index = info->gotsize;
            gotent->offset = offset;
            gotent->reloc = xballoc(b, sizeof(arelent));
            gotent->reloc->sym_ptr_ptr = reloc->sym_ptr_ptr;
            gotent->reloc->address = offset;
            gotent->reloc->addend = reloc->addend;
            gotent->reloc->howto = info->reloc_64;
            offset += sizeof(void*);
            info->gotsize += 1;

  if (offset >= 0x8000)
    FEerror("Too many entries in GOT (GOT full, merci ALPHA)",0);
  if (info->gotsize > 0) {
    info->sgot = bfd_make_section(b, ".got");
    info->sgot->flags = SEC_ALLOC|SEC_RELOC|SEC_LOAD;
    if (!bfd_set_section_size(b,info->sgot,offset))
      FEerror("Cannot set got section size",0);
    if (info->sgot->alignment_power < 4)
      info->sgot->alignment_power = 4;      /* Set GOT relocations */
    info->sgot->relocation = xballoc(b, 
    bfd_hash_traverse(&info->got_table, (void*)alphaelf_got_traverse, 
    info->sgot->reloc_count = info->gotsize;
  return info->sgot;


/* alphaelf_fix_relocs -- patches the relocation for GOT */
static void 
alphaelf_fix_relocs(bfd *b,asymbol ** symbols,int symbol_count,
                   alphaelf_got_info *info) {

  int i;
  asymbol **gpdisp_ptr = NULL;
  asection *p;

  /* Make a gpdisp symbol at the top of the .got section */
  gpdisp = xballoc(b, sizeof(*gpdisp));
  gpdisp->value = 0;
  gpdisp->flags = BSF_LOCAL|BSF_SECTION_SYM;
  gpdisp->section = info->sgot ? info->sgot : bfd_abs_section_ptr;
  gpdisp->udata.p = NULL;

  if (!info->sgot)

  gpdisp_ptr = xballoc(b, sizeof(asymbol*));
  *gpdisp_ptr = gpdisp;
  /* Iterate on sections and relocations */
  for (p=b->sections; p; p=p->next)
    if ((p->flags & SEC_ALLOC) && (p->flags & SEC_RELOC)) {
      for (i=0; i<p->reloc_count; i++) {
        arelent *reloc = p->relocation+i;
        if (reloc->howto==info->reloc_literal) {
          const char *name = msymbol_name(b,*reloc->sym_ptr_ptr,reloc->addend);
          alphaelf_got_entry *gotent = 
            (alphaelf_got_entry*) bfd_hash_lookup(&info->got_table, name, 
          /* ELF_LITERAL relocations will refer
           * to the GPDISP symbol and have the GOT index
           * in the addend */
          reloc->addend = gotent->offset;
          reloc->sym_ptr_ptr = gpdisp_ptr;




mips is still more involved if a hairier example is needed :-).

So I think that all we need is to identify how to 1) capture the gp
symbol value and 2) rewrite the relocs referring thereto to refer to a
got table entry which is then constructed to point to the right
address.  Hopefully this will ring some bells in your mind given its
familiarity with ia64.

The way to debug this is to make a saved_pre_gcl image in unixport
with a new sfaslbfd_ia64.c compiled in (the ia64-linux.h needs to be
modified following the alpha-linux.h), and debugging enabled
(--enable-debug on the configure command line).  Then fire up gdb on
saved_pre_gcl, and try loading a .o file, breaking at fasload and
stepping through each of the routines, especially

Take care, and thanks again,

> Richard

Camm Maguire                                            address@hidden
"The earth is but one country, and mankind its citizens."  --  Baha'u'llah

reply via email to

[Prev in Thread] Current Thread [Next in Thread]