~ubuntu-branches/ubuntu/quantal/elfutils/quantal

« back to all changes in this revision

Viewing changes to backends/ppc_symbol.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2006-08-27 15:48:23 UTC
  • Revision ID: james.westby@ubuntu.com-20060827154823-mjwd7ydlbxgwqn4u
Tags: upstream-0.123
ImportĀ upstreamĀ versionĀ 0.123

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* PPC specific symbolic name handling.
 
2
   Copyright (C) 2004, 2005 Red Hat, Inc.
 
3
   This file is part of Red Hat elfutils.
 
4
   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
 
5
 
 
6
   Red Hat elfutils is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by the
 
8
   Free Software Foundation; version 2 of the License.
 
9
 
 
10
   Red Hat elfutils is distributed in the hope that it will be useful, but
 
11
   WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
   General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU General Public License along
 
16
   with Red Hat elfutils; if not, write to the Free Software Foundation,
 
17
   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
 
18
 
 
19
   Red Hat elfutils is an included package of the Open Invention Network.
 
20
   An included package of the Open Invention Network is a package for which
 
21
   Open Invention Network licensees cross-license their patents.  No patent
 
22
   license is granted, either expressly or impliedly, by designation as an
 
23
   included package.  Should you wish to participate in the Open Invention
 
24
   Network licensing program, please visit www.openinventionnetwork.com
 
25
   <http://www.openinventionnetwork.com>.  */
 
26
 
 
27
#ifdef HAVE_CONFIG_H
 
28
# include <config.h>
 
29
#endif
 
30
 
 
31
#include <assert.h>
 
32
#include <elf.h>
 
33
#include <stddef.h>
 
34
#include <string.h>
 
35
 
 
36
#define BACKEND         ppc_
 
37
#include "libebl_CPU.h"
 
38
 
 
39
 
 
40
/* Check for the simple reloc types.  */
 
41
Elf_Type
 
42
ppc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
 
43
{
 
44
  switch (type)
 
45
    {
 
46
    case R_PPC_ADDR32:
 
47
    case R_PPC_UADDR32:
 
48
      return ELF_T_WORD;
 
49
    case R_PPC_UADDR16:
 
50
      return ELF_T_HALF;
 
51
    default:
 
52
      return ELF_T_NUM;
 
53
    }
 
54
}
 
55
 
 
56
 
 
57
const char *
 
58
ppc_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
 
59
                      size_t len __attribute__ ((unused)))
 
60
{
 
61
  switch (tag)
 
62
    {
 
63
    case DT_PPC_GOT:
 
64
      return "PPC_GOT";
 
65
    default:
 
66
      break;
 
67
    }
 
68
  return NULL;
 
69
}
 
70
 
 
71
 
 
72
bool
 
73
ppc_dynamic_tag_check (int64_t tag)
 
74
{
 
75
  return tag == DT_PPC_GOT;
 
76
}
 
77
 
 
78
 
 
79
/* Look for DT_PPC_GOT.  */
 
80
static bool
 
81
find_dyn_got (Elf *elf, GElf_Ehdr *ehdr, GElf_Addr *addr)
 
82
{
 
83
  for (int i = 0; i < ehdr->e_phnum; ++i)
 
84
    {
 
85
      GElf_Phdr phdr_mem;
 
86
      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
 
87
      if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
 
88
        continue;
 
89
 
 
90
      Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
 
91
      GElf_Shdr shdr_mem;
 
92
      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
 
93
      Elf_Data *data = elf_getdata (scn, NULL);
 
94
      if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL)
 
95
        for (unsigned int j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
 
96
          {
 
97
            GElf_Dyn dyn_mem;
 
98
            GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
 
99
            if (dyn != NULL && dyn->d_tag == DT_PPC_GOT)
 
100
              {
 
101
                *addr = dyn->d_un.d_ptr;
 
102
                return true;
 
103
              }
 
104
          }
 
105
 
 
106
      /* There is only one PT_DYNAMIC entry.  */
 
107
      break;
 
108
    }
 
109
 
 
110
  return false;
 
111
}
 
112
 
 
113
 
 
114
/* Check whether given symbol's st_value and st_size are OK despite failing
 
115
   normal checks.  */
 
116
bool
 
117
ppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
 
118
                          const char *name, const GElf_Shdr *destshdr)
 
119
{
 
120
  if (name == NULL)
 
121
    return false;
 
122
 
 
123
  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
 
124
    {
 
125
      GElf_Addr gotaddr;
 
126
      if (find_dyn_got (elf, ehdr, &gotaddr))
 
127
        return sym->st_value == gotaddr;
 
128
      return sym->st_value == destshdr->sh_addr + 4;
 
129
    }
 
130
 
 
131
  const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
 
132
  if (sname == NULL)
 
133
    return false;
 
134
 
 
135
  if (strcmp (name, "_SDA_BASE_") == 0)
 
136
    return (strcmp (sname, ".sdata") == 0
 
137
            && sym->st_value == destshdr->sh_addr + 0x8000
 
138
            && sym->st_size == 0);
 
139
 
 
140
  if (strcmp (name, "_SDA2_BASE_") == 0)
 
141
    return (strcmp (sname, ".sdata2") == 0
 
142
            && sym->st_value == destshdr->sh_addr + 0x8000
 
143
            && sym->st_size == 0);
 
144
 
 
145
  return false;
 
146
}
 
147
 
 
148
 
 
149
/* Check if backend uses a bss PLT in this file.  */
 
150
bool
 
151
ppc_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr)
 
152
{
 
153
  GElf_Addr addr;
 
154
  return ! find_dyn_got (elf, ehdr, &addr);
 
155
}