1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* PPC specific symbolic name handling.
2fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard   Copyright (C) 2004, 2005, 2007, 2014, 2015 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
5b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
7de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
8b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
21de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
25361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
28de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#ifdef HAVE_CONFIG_H
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper# include <config.h>
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#endif
33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <assert.h>
35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <elf.h>
36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stddef.h>
37653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath#include <string.h>
38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
39cd60ea83050d9fb48c3204005f475df460f433b6Roland McGrath#define BACKEND		ppc_
40cd60ea83050d9fb48c3204005f475df460f433b6Roland McGrath#include "libebl_CPU.h"
41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Check for the simple reloc types.  */
44b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperElf_Type
45cd60ea83050d9fb48c3204005f475df460f433b6Roland McGrathppc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  switch (type)
48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case R_PPC_ADDR32:
50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case R_PPC_UADDR32:
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ELF_T_WORD;
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    case R_PPC_UADDR16:
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ELF_T_HALF;
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    default:
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return ELF_T_NUM;
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
59b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper
60b03b05785914250d53d31e966373617f6104bd9dUlrich Drepperconst char *
61b03b05785914250d53d31e966373617f6104bd9dUlrich Drepperppc_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
62b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper		      size_t len __attribute__ ((unused)))
63b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper{
64b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper  switch (tag)
65b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper    {
66b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper    case DT_PPC_GOT:
67b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper      return "PPC_GOT";
68b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper    default:
69b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper      break;
70b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper    }
71b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper  return NULL;
72b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper}
73b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper
74b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper
75b03b05785914250d53d31e966373617f6104bd9dUlrich Drepperbool
76b03b05785914250d53d31e966373617f6104bd9dUlrich Drepperppc_dynamic_tag_check (int64_t tag)
77b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper{
78b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper  return tag == DT_PPC_GOT;
79b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper}
80b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper
81b03b05785914250d53d31e966373617f6104bd9dUlrich Drepper
82f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath/* Look for DT_PPC_GOT.  */
83f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrathstatic bool
84712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaardfind_dyn_got (Elf *elf, GElf_Addr *addr)
85f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath{
86712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  size_t phnum;
87712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  if (elf_getphdrnum (elf, &phnum) != 0)
88712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard    return false;
89712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard
90712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  for (size_t i = 0; i < phnum; ++i)
91f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath    {
92c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper      GElf_Phdr phdr_mem;
93c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
94c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper      if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
95c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	continue;
96c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper
97c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper      Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
98f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath      GElf_Shdr shdr_mem;
99f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
100c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper      Elf_Data *data = elf_getdata (scn, NULL);
101d973206f716d441634f3b937be9c8c5b8b6250dbMark Wielaard      if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL
102d973206f716d441634f3b937be9c8c5b8b6250dbMark Wielaard	  && shdr->sh_entsize != 0)
103c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	for (unsigned int j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
104c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	  {
105c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	    GElf_Dyn dyn_mem;
106c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	    GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
107c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	    if (dyn != NULL && dyn->d_tag == DT_PPC_GOT)
108c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	      {
109c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		*addr = dyn->d_un.d_ptr;
110c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper		return true;
111c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	      }
112c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper	  }
113c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper
114c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper      /* There is only one PT_DYNAMIC entry.  */
115c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper      break;
116f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath    }
117f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath
118f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath  return false;
119f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath}
120f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath
121c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper
122f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath/* Check whether given symbol's st_value and st_size are OK despite failing
123f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath   normal checks.  */
124653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathbool
125c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepperppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
126c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper			  const char *name, const GElf_Shdr *destshdr)
127653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath{
128653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath  if (name == NULL)
129653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath    return false;
130653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
131c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
132653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath    {
133cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      /* In -msecure-plt mode, DT_PPC_GOT is present and must match.  */
134f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath      GElf_Addr gotaddr;
135712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard      if (find_dyn_got (elf, &gotaddr))
136f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath	return sym->st_value == gotaddr;
137cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath
138cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      /* In -mbss-plt mode, any place in the section is valid.  */
139cb6d865011ad98a8ac2018f072f396a2268739caRoland McGrath      return true;
140653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath    }
141653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
142653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath  const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
143653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath  if (sname == NULL)
144653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath    return false;
145653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
146fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard  /* Small data area.  Normally points to .sdata, in which case we
147fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard     check it is at an offset of 0x8000.  It might however fall in the
148fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard     .data section, in which case we cannot check the offset.  The
149fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard     size always should be zero.  */
150c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper  if (strcmp (name, "_SDA_BASE_") == 0)
151fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard    return (((strcmp (sname, ".sdata") == 0
152fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard	      && sym->st_value == destshdr->sh_addr + 0x8000)
153fd2e84cb31fa7585baa7daa9dae03a8ac725ae05Mark Wielaard	     || strcmp (sname, ".data") == 0)
154653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	    && sym->st_size == 0);
155653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
156c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper  if (strcmp (name, "_SDA2_BASE_") == 0)
157c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper    return (strcmp (sname, ".sdata2") == 0
158653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	    && sym->st_value == destshdr->sh_addr + 0x8000
159653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath	    && sym->st_size == 0);
160653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
161653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath  return false;
162653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath}
163653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath
164c5c33a6a2ce5ea400ac5d06b3c2f15808f68b803Ulrich Drepper
165653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath/* Check if backend uses a bss PLT in this file.  */
166653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrathbool
167712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaardppc_bss_plt_p (Elf *elf)
168653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath{
169f8873cb86317d18399593eb95947e0c543bc9d72Roland McGrath  GElf_Addr addr;
170712c8faddc08844fb1f2814c8b6e817f03b0698eMark Wielaard  return ! find_dyn_got (elf, &addr);
171653d3763e986da9f1c8a92ff9103d85c534754cdRoland McGrath}
172