<commit_before>/*********************************************************************
 *
 * Copyright (C) 2008,  <NAME>
 *
 * Filename:      elf.cc
 * Author:        <NAME> <<EMAIL>>
 * Description:   ELF implementation
 *
 * $Id:$
 *
 ********************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <libelf.h>
#include <dwarf.h>
#include <elfutils/libdw.h>

#include <utils.h>
#include <elf.hh>


static int symbol_cmp(const void *_a, const void *_b)
{
  ElfSymbol *a = *(ElfSymbol**)_a;
  ElfSymbol *b = *(ElfSymbol**)_b;

  return a->addr - b->addr;
}

void CibylElf::handleSymtab(Elf_Scn *scn)
{
  Elf32_Shdr *shdr = elf32_getshdr(scn);
  Elf_Data *data = elf_getdata(scn, NULL);
  Elf32_Sym *s = (Elf32_Sym *)data->d_buf;
  int n_syms = 0;
  int n_fns = 0;
  int n_datas = 0;
  int n = data->d_size / sizeof(Elf32_Sym);

  panic_if(n <= 0,
           "Section data too small (%zd) - no symbols\n",
           data->d_size);

  /* Allocate big enough tables of symbols */
  this->symbols = (ElfSymbol**)xcalloc(n, sizeof(ElfSymbol));
  this->functionSymbols = (ElfSymbol**)xcalloc(n, sizeof(ElfSymbol));
  this->dataSymbols = (ElfSymbol**)xcalloc(n, sizeof(ElfSymbol));

  /* Iterate through all symbols */
  for (int i = 0; i < n; i++)
    {
      const char *sym_name = elf_strptr(this->elf, shdr->sh_link, s->st_name);
      int type = ELF32_ST_TYPE(s->st_info);
      int binding = ELF32_ST_BIND(s->st_info);

      /* Ohh... This is an interesting symbol, add it! */
      if ( type == STT_FUNC) {
          ElfSymbol *sym = new ElfSymbol(i, binding, s->st_value,
              s->st_size, type, sym_name);

          this->symbols[n_syms++] = this->functionSymbols[n_fns++] = sym;
          ght_insert(this->symbols_by_addr, (void*)sym,
              sizeof(sym->addr), (void*)&sym->addr);
      }
      else if (type == STT_OBJECT || type == STT_COMMON || type == STT_TLS)
        this->symbols[n_syms++] = this->dataSymbols[n_datas++] = new ElfSymbol(i, binding, (uint32_t)s->st_value,
                                                                               (uint32_t)s->st_size,
                                                                               type, sym_name);
      s++;
    }

  this->n_symbols = n_syms;
  this->n_functionSymbols = n_fns;
  this->n_dataSymbols = n_datas;

  panic_if(n_symbols <= 0,
           "No symbols in the ELF file (file stripped?)\n");

  /* Insert all symbols into a hash table */
  for (int i = 0; i < n_syms; i++)
    {
      ght_insert(this->symtable, (void*)this->symbols[i],
                 sizeof(uint32_t), (void*)&this->symbols[i]->index);
    }
}

static int reloc_cmp(const void *_a, const void *_b)
{
  ElfReloc *a = *(ElfReloc**)_a;
  ElfReloc *b = *(ElfReloc**)_b;
  int type_diff = a->type - b->type;
  int addr_diff = a->addr - b->addr;

  /* First sort by type, then address */
  if (type_diff != 0)
    return type_diff;

  return addr_diff;
}

extern "C" int mips_arg_size (Elf *elf, Dwarf_Die *functypedie, Dwarf_Attribute *attr);

void CibylElf::handleDwarfFunction(Dwarf_Die *fun_die)
{
  Dwarf_Die result;
  Dwarf_Attribute attr_mem;
  Dwarf_Attribute *attr;
  Dwarf_Addr addr;

  if (dwarf_lowpc(fun_die, &addr) != 0)
    return;
  ElfSymbol *sym = this->getSymbolByAddr(addr);

  if (!sym)
    return;

  if (dwarf_child (fun_die, &result) != 0)
    return;

  attr = dwarf_attr_integrate(fun_die, DW_AT_type, &attr_mem);

  sym->ret_size = mips_arg_size(elf, fun_die, attr);

  int n_args = 0;
  do {
      int arg_size;

      switch (dwarf_tag (&result))
      {
      case DW_TAG_formal_parameter:
        attr = dwarf_attr_integrate(&result, DW_AT_type, &attr_mem);
        arg_size = mips_arg_size(elf, fun_die, attr);

        if (arg_size != 1)
          {
            /* Better safe than sorry - skip this */
            n_args = -1;
            break;
          }

        n_args++;
        break;
      case DW_TAG_inlined_subroutine:
        /* Recurse further down */
        this->handleDwarfFunction(&result);
        break;
      default:
        break;
      }
  } while(dwarf_siblingof(&result, &result) == 0);

  sym->n_args = n_args;
}


CibylElf::CibylElf(const char *filename)
{
  Elf_Scn *scn = NULL;<commit_msg>translator: DWARF: Handle varargs and correct break on big arguments<commit_after>/*********************************************************************
 *
 * Copyright (C) 2008,  <NAME>
 *
 * Filename:      elf.cc
 * Author:        <NAME> <<EMAIL>>
 * Description:   ELF implementation
 *
 * $Id:$
 *
 ********************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <fcntl.h>
#include <libelf.h>
#include <dwarf.h>
#include <elfutils/libdw.h>

#include <utils.h>
#include <elf.hh>


static int symbol_cmp(const void *_a, const void *_b)
{
  ElfSymbol *a = *(ElfSymbol**)_a;
  ElfSymbol *b = *(ElfSymbol**)_b;

  return a->addr - b->addr;
}

void CibylElf::handleSymtab(Elf_Scn *scn)
{
  Elf32_Shdr *shdr = elf32_getshdr(scn);
  Elf_Data *data = elf_getdata(scn, NULL);
  Elf32_Sym *s = (Elf32_Sym *)data->d_buf;
  int n_syms = 0;
  int n_fns = 0;
  int n_datas = 0;
  int n = data->d_size / sizeof(Elf32_Sym);

  panic_if(n <= 0,
           "Section data too small (%zd) - no symbols\n",
           data->d_size);

  /* Allocate big enough tables of symbols */
  this->symbols = (ElfSymbol**)xcalloc(n, sizeof(ElfSymbol));
  this->functionSymbols = (ElfSymbol**)xcalloc(n, sizeof(ElfSymbol));
  this->dataSymbols = (ElfSymbol**)xcalloc(n, sizeof(ElfSymbol));

  /* Iterate through all symbols */
  for (int i = 0; i < n; i++)
    {
      const char *sym_name = elf_strptr(this->elf, shdr->sh_link, s->st_name);
      int type = ELF32_ST_TYPE(s->st_info);
      int binding = ELF32_ST_BIND(s->st_info);

      /* Ohh... This is an interesting symbol, add it! */
      if ( type == STT_FUNC) {
          ElfSymbol *sym = new ElfSymbol(i, binding, s->st_value,
              s->st_size, type, sym_name);

          this->symbols[n_syms++] = this->functionSymbols[n_fns++] = sym;
          ght_insert(this->symbols_by_addr, (void*)sym,
              sizeof(sym->addr), (void*)&sym->addr);
      }
      else if (type == STT_OBJECT || type == STT_COMMON || type == STT_TLS)
        this->symbols[n_syms++] = this->dataSymbols[n_datas++] = new ElfSymbol(i, binding, (uint32_t)s->st_value,
                                                                               (uint32_t)s->st_size,
                                                                               type, sym_name);
      s++;
    }

  this->n_symbols = n_syms;
  this->n_functionSymbols = n_fns;
  this->n_dataSymbols = n_datas;

  panic_if(n_symbols <= 0,
           "No symbols in the ELF file (file stripped?)\n");

  /* Insert all symbols into a hash table */
  for (int i = 0; i < n_syms; i++)
    {
      ght_insert(this->symtable, (void*)this->symbols[i],
                 sizeof(uint32_t), (void*)&this->symbols[i]->index);
    }
}

static int reloc_cmp(const void *_a, const void *_b)
{
  ElfReloc *a = *(ElfReloc**)_a;
  ElfReloc *b = *(ElfReloc**)_b;
  int type_diff = a->type - b->type;
  int addr_diff = a->addr - b->addr;

  /* First sort by type, then address */
  if (type_diff != 0)
    return type_diff;

  return addr_diff;
}

extern "C" int mips_arg_size (Elf *elf, Dwarf_Die *functypedie, Dwarf_Attribute *attr);

void CibylElf::handleDwarfFunction(Dwarf_Die *fun_die)
{
  Dwarf_Die result;
  Dwarf_Attribute attr_mem;
  Dwarf_Attribute *attr;
  Dwarf_Addr addr;

  if (dwarf_lowpc(fun_die, &addr) != 0)
    return;
  ElfSymbol *sym = this->getSymbolByAddr(addr);

  if (!sym)
    return;

  if (dwarf_child (fun_die, &result) != 0)
    return;

  attr = dwarf_attr_integrate(fun_die, DW_AT_type, &attr_mem);

  sym->ret_size = mips_arg_size(elf, fun_die, attr);

  int n_args = 0;
  do {
      int arg_size;

      switch (dwarf_tag (&result))
      {
      case DW_TAG_unspecified_parameters:
    	  /* varargs etc */
          n_args = -1;
    	  goto out;
      case DW_TAG_formal_parameter:
        attr = dwarf_attr_integrate(&result, DW_AT_type, &attr_mem);
        arg_size = mips_arg_size(elf, fun_die, attr);

        if (arg_size != 1)
          {
            /* Better safe than sorry - skip this */
            n_args = -1;
            goto out;
          }

        n_args++;
        break;
      case DW_TAG_inlined_subroutine:
        /* Recurse further down */
        this->handleDwarfFunction(&result);
        break;
      default:
        break;
      }
  } while(dwarf_siblingof(&result, &result) == 0);

out:
  sym->n_args = n_args;
}


CibylElf::CibylElf(const char *filename)
{
  Elf_Scn *scn = NULL;
{'fraction_non_alphanumeric': 0.17107030900134348, 'fraction_numerical': 0.008620689655172414, 'mean_word_length': 2.6224655312246554, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 113, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '950999', 'n_tokens_mistral': 3373, 'n_tokens_neox': 3222, 'n_words': 704}