Blame backends/riscv_symbol.c

Packit Service 97d2fb
/* RISC-V specific symbolic name handling.
Packit Service 97d2fb
   This file is part of elfutils.
Packit Service 97d2fb
Packit Service 97d2fb
   This file is free software; you can redistribute it and/or modify
Packit Service 97d2fb
   it under the terms of either
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU Lesser General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 3 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or
Packit Service 97d2fb
Packit Service 97d2fb
     * the GNU General Public License as published by the Free
Packit Service 97d2fb
       Software Foundation; either version 2 of the License, or (at
Packit Service 97d2fb
       your option) any later version
Packit Service 97d2fb
Packit Service 97d2fb
   or both in parallel, as here.
Packit Service 97d2fb
Packit Service 97d2fb
   elfutils is distributed in the hope that it will be useful, but
Packit Service 97d2fb
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 97d2fb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 97d2fb
   General Public License for more details.
Packit Service 97d2fb
Packit Service 97d2fb
   You should have received copies of the GNU General Public License and
Packit Service 97d2fb
   the GNU Lesser General Public License along with this program.  If
Packit Service 97d2fb
   not, see <http://www.gnu.org/licenses/>.  */
Packit Service 97d2fb
Packit Service 97d2fb
#ifdef HAVE_CONFIG_H
Packit Service 97d2fb
# include <config.h>
Packit Service 97d2fb
#endif
Packit Service 97d2fb
Packit Service 97d2fb
#include <assert.h>
Packit Service 97d2fb
#include <elf.h>
Packit Service 97d2fb
#include <stddef.h>
Packit Service 97d2fb
#include <string.h>
Packit Service 97d2fb
Packit Service 97d2fb
#define BACKEND riscv_
Packit Service 97d2fb
#include "libebl_CPU.h"
Packit Service 97d2fb
Packit Service 97d2fb
Packit Service 97d2fb
/* Check for the simple reloc types.  */
Packit Service 97d2fb
Elf_Type
Packit Service 97d2fb
riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
Packit Service 97d2fb
			 int *addsub)
Packit Service 97d2fb
{
Packit Service 97d2fb
  switch (type)
Packit Service 97d2fb
    {
Packit Service 97d2fb
    case R_RISCV_SET8:
Packit Service 97d2fb
      return ELF_T_BYTE;
Packit Service 97d2fb
    case R_RISCV_SET16:
Packit Service 97d2fb
      return ELF_T_HALF;
Packit Service 97d2fb
    case R_RISCV_32:
Packit Service 97d2fb
    case R_RISCV_SET32:
Packit Service 97d2fb
      return ELF_T_WORD;
Packit Service 97d2fb
    case R_RISCV_64:
Packit Service 97d2fb
      return ELF_T_XWORD;
Packit Service 97d2fb
    case R_RISCV_ADD16:
Packit Service 97d2fb
      *addsub = 1;
Packit Service 97d2fb
      return ELF_T_HALF;
Packit Service 97d2fb
    case R_RISCV_SUB16:
Packit Service 97d2fb
      *addsub = -1;
Packit Service 97d2fb
      return ELF_T_HALF;
Packit Service 97d2fb
    case R_RISCV_ADD32:
Packit Service 97d2fb
      *addsub = 1;
Packit Service 97d2fb
      return ELF_T_WORD;
Packit Service 97d2fb
    case R_RISCV_SUB32:
Packit Service 97d2fb
      *addsub = -1;
Packit Service 97d2fb
      return ELF_T_WORD;
Packit Service 97d2fb
    case R_RISCV_ADD64:
Packit Service 97d2fb
      *addsub = 1;
Packit Service 97d2fb
      return ELF_T_XWORD;
Packit Service 97d2fb
    case R_RISCV_SUB64:
Packit Service 97d2fb
      *addsub = -1;
Packit Service 97d2fb
      return ELF_T_XWORD;
Packit Service 97d2fb
    default:
Packit Service 97d2fb
      return ELF_T_NUM;
Packit Service 97d2fb
    }
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Check whether machine flags are valid.  */
Packit Service 97d2fb
bool
Packit Service 97d2fb
riscv_machine_flag_check (GElf_Word flags)
Packit Service 97d2fb
{
Packit Service 97d2fb
  return ((flags &~ (EF_RISCV_RVC
Packit Service 97d2fb
		     | EF_RISCV_FLOAT_ABI)) == 0);
Packit Service 97d2fb
}
Packit Service 97d2fb
Packit Service 97d2fb
/* Check whether given symbol's st_value and st_size are OK despite failing
Packit Service 97d2fb
   normal checks.  */
Packit Service 97d2fb
bool
Packit Service 97d2fb
riscv_check_special_symbol (Elf *elf, const GElf_Sym *sym,
Packit Service 97d2fb
			    const char *name, const GElf_Shdr *destshdr)
Packit Service 97d2fb
{
Packit Service 97d2fb
  if (name == NULL)
Packit Service 97d2fb
    return false;
Packit Service 97d2fb
Packit Service 97d2fb
  size_t shstrndx;
Packit Service 97d2fb
  if (elf_getshdrstrndx (elf, &shstrndx) != 0)
Packit Service 97d2fb
    return false;
Packit Service 97d2fb
  const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
Packit Service 97d2fb
  if (sname == NULL)
Packit Service 97d2fb
    return false;
Packit Service 97d2fb
Packit Service 97d2fb
  /* _GLOBAL_OFFSET_TABLE_ points to the start of the .got section, but it
Packit Service 97d2fb
     is preceded by the .got.plt section in the output .got section.  */
Packit Service 97d2fb
  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
Packit Service 97d2fb
    return (strcmp (sname, ".got") == 0
Packit Service 97d2fb
	    && sym->st_value >= destshdr->sh_addr
Packit Service 97d2fb
	    && sym->st_value < destshdr->sh_addr + destshdr->sh_size);
Packit Service 97d2fb
Packit Service 97d2fb
  /* __global_pointer$ points to the .sdata section with an offset of
Packit Service 97d2fb
     0x800.  It might however fall in the .got section, in which case we
Packit Service 97d2fb
     cannot check the offset.  The size always should be zero.  */
Packit Service 97d2fb
  if (strcmp (name, "__global_pointer$") == 0)
Packit Service 97d2fb
    return (((strcmp (sname, ".sdata") == 0
Packit Service 97d2fb
	      && sym->st_value == destshdr->sh_addr + 0x800)
Packit Service 97d2fb
	     || strcmp (sname, ".got") == 0)
Packit Service 97d2fb
	    && sym->st_size == 0);
Packit Service 97d2fb
Packit Service 97d2fb
  return false;
Packit Service 97d2fb
}