~ubuntu-branches/debian/sid/grub2/sid-200907171837

« back to all changes in this revision

Viewing changes to kern/powerpc/dl.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Millan
  • Date: 2009-07-02 13:23:51 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702132351-tanpn0ryyijp93gu
Tags: 1.96+20090702-1
* New SVN snapshot.
* rules: Remove duplicated files in sparc64-ieee1275 port.
* rules: Comment out -DGRUB_ASSUME_LINUX_HAS_FB_SUPPORT=1 setting.  We'll
  re-evaluate using it when it's more mature.  (Closes: #535026).

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
grub_err_t
27
27
grub_arch_dl_check_header (void *ehdr)
28
28
{
29
 
  Elf32_Ehdr *e = ehdr;
 
29
  Elf_Ehdr *e = ehdr;
30
30
 
31
31
  /* Check the magic numbers.  */
32
32
  if (e->e_ident[EI_CLASS] != ELFCLASS32
42
42
grub_err_t
43
43
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
44
44
{
45
 
  Elf32_Ehdr *e = ehdr;
46
 
  Elf32_Shdr *s;
47
 
  Elf32_Sym *symtab;
48
 
  Elf32_Word entsize;
 
45
  Elf_Ehdr *e = ehdr;
 
46
  Elf_Shdr *s;
 
47
  Elf_Word entsize;
49
48
  unsigned i;
50
 
  
 
49
 
51
50
  /* Find a symbol table.  */
52
 
  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
 
51
  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
53
52
       i < e->e_shnum;
54
 
       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
 
53
       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
55
54
    if (s->sh_type == SHT_SYMTAB)
56
55
      break;
57
56
 
58
57
  if (i == e->e_shnum)
59
58
    return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
60
 
  
61
 
  symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
 
59
 
62
60
  entsize = s->sh_entsize;
63
 
  
64
 
  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
 
61
 
 
62
  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
65
63
       i < e->e_shnum;
66
 
       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
 
64
       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
67
65
    if (s->sh_type == SHT_RELA)
68
66
      {
69
67
        grub_dl_segment_t seg;
75
73
 
76
74
        if (seg)
77
75
          {
78
 
            Elf32_Rela *rel, *max;
79
 
            
80
 
            for (rel = (Elf32_Rela *) ((char *) e + s->sh_offset),
 
76
            Elf_Rela *rel, *max;
 
77
 
 
78
            for (rel = (Elf_Rela *) ((char *) e + s->sh_offset),
81
79
                   max = rel + s->sh_size / s->sh_entsize;
82
80
                 rel < max;
83
81
                 rel++)
84
82
              {
85
 
                Elf32_Word *addr;
86
 
                Elf32_Sym *sym;
 
83
                Elf_Word *addr;
 
84
                Elf_Sym *sym;
87
85
                grub_uint32_t value;
88
 
                
 
86
 
89
87
                if (seg->size < rel->r_offset)
90
88
                  return grub_error (GRUB_ERR_BAD_MODULE,
91
89
                                     "reloc offset is out of the segment");
92
 
                
93
 
                addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset);
94
 
                sym = (Elf32_Sym *) ((char *) symtab
95
 
                                     + entsize * ELF32_R_SYM (rel->r_info));
96
 
                
 
90
 
 
91
                addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset);
 
92
                sym = (Elf_Sym *) ((char *) mod->symtab
 
93
                                     + entsize * ELF_R_SYM (rel->r_info));
 
94
 
97
95
                /* On the PPC the value does not have an explicit
98
96
                   addend, add it.  */
99
97
                value = sym->st_value + rel->r_addend;
100
 
                switch (ELF32_R_TYPE (rel->r_info))
 
98
                switch (ELF_R_TYPE (rel->r_info))
101
99
                  {
102
100
                  case R_PPC_ADDR16_LO:
103
 
                    *(Elf32_Half *) addr = value;
 
101
                    *(Elf_Half *) addr = value;
104
102
                    break;
105
 
                    
 
103
 
106
104
                  case R_PPC_REL24:
107
105
                    {
108
 
                      Elf32_Sword delta = value - (Elf32_Word) addr;
109
 
                      
 
106
                      Elf_Sword delta = value - (Elf_Word) addr;
 
107
 
110
108
                      if (delta << 6 >> 6 != delta)
111
109
                        return grub_error (GRUB_ERR_BAD_MODULE, "Relocation overflow");
112
110
                      *addr = (*addr & 0xfc000003) | (delta & 0x3fffffc);
113
111
                      break;
114
112
                    }
115
 
                    
 
113
 
116
114
                  case R_PPC_ADDR16_HA:
117
 
                    *(Elf32_Half *) addr = (value + 0x8000) >> 16;
 
115
                    *(Elf_Half *) addr = (value + 0x8000) >> 16;
118
116
                    break;
119
 
                    
 
117
 
120
118
                  case R_PPC_ADDR32:
121
119
                    *addr = value;
122
120
                    break;
123
 
                    
 
121
 
124
122
                  case R_PPC_REL32:
125
 
                    *addr = value - (Elf32_Word) addr;
 
123
                    *addr = value - (Elf_Word) addr;
126
124
                    break;
127
 
                    
 
125
 
128
126
                  default:
129
127
                    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
130
128
                                       "This relocation (%d) is not implemented yet",
131
 
                                       ELF32_R_TYPE (rel->r_info));
 
129
                                       ELF_R_TYPE (rel->r_info));
132
130
                  }
133
131
              }
134
132
          }
135
133
      }
136
 
  
 
134
 
137
135
  return GRUB_ERR_NONE;
138
136
}