Esempio n. 1
0
Info & Block::putSymsInScope(const symbol::Symbol & sym, Block * block, Info & info)
{
    // We put the sym (which is defined in block) in this block and pull all its companions too.
    Info & i = addSym(sym, info);
    Data * data = i.data;
    // emplace called the Info's copy ctor so a new Data has been allocated
    dm->registerData(data);//, __LINE__, __FILE__);
    // We put all the shared syms in this scope
    if (!data->hasOneOwner())
    {
        for (const auto & _sym : data->sharedSyms)
        {
            if (sym != _sym)
            {
                Info & _i = block->symMap.find(_sym)->second;
                Data * old = _i.data;
                // we set _i.data to nullptr to avoid the data copy when cloning _i
                _i.data = nullptr;
                addSym(_sym, _i).data = data;
                _i.data = old;
            }
        }
    }

    return i;
}
Esempio n. 2
0
Info & Block::putAndClear(const symbol::Symbol & sym, ast::Exp * exp)
{
    tools::SymbolMap<Info>::iterator it;
    Block * block = getDefBlock(sym, it, false);
    if (block)
    {
        Info & info = it->second;
        if (block == this)
        {
            if (info.data->hasOneOwner())
            {
                info.cleared = true;
                info.local = Info::Local::INFO_TRUE;
                return info;
            }
            else
            {
                info.data->rem(sym);
                info.data = nullptr;
                info.cleared = true;
                info.local = Info::Local::INFO_TRUE;
                return info;
            }
        }
        else
        {
            if (info.data->hasOneOwner())
            {
                Data * old = info.data;
                info.data = nullptr;
                Info & i = addSym(sym, info);
                info.data = old;
                i.cleared = true;
                i.local = Info::Local::INFO_TRUE;
                return i;
            }
            else
            {
                Info & i = putSymsInScope(sym, block, info);
                i.data->rem(sym);
                i.data = nullptr;
                i.cleared = true;
                i.local = Info::Local::INFO_TRUE;
                return i;
            }
        }
    }
    else
    {
        Info & i = addSym(sym, nullptr);
        i.local = Info::Local::INFO_TRUE;

        return i;
    }
}
Esempio n. 3
0
Info & Block::setDefaultData(const symbol::Symbol & sym)
{
    Info & i = addSym(sym, new Data(false, sym));
    i.local = Info::Local::INFO_FALSE;
    i.type = DataManager::getSymInScilabContext(getGVN(), sym, i.exists);
    addGlobal(sym);
    dm->registerData(i.data);//, __LINE__, __FILE__);

    return i;
}
Esempio n. 4
0
/*-----------------------------------------------------------------*/
void
deallocParms (value * val)
{
  value *lval;

  for (lval = val; lval; lval = lval->next)
    {
      /* unmark is myparm */
      lval->sym->ismyparm = 0;

      /* delete it from the symbol table  */
      deleteSym (SymbolTab, lval->sym, lval->sym->name);

      if (!lval->sym->isref)
        {
          lval->sym->allocreq = 0;
            werror (W_NO_REFERENCE,
                    currFunc ? currFunc->name : "(unknown)",
                    "function argument", lval->sym->name);
        }

      /* move the rname if any to the name for both val & sym */
      /* and leave a copy of it in the symbol table           */
      if (lval->sym->rname[0])
        {
          char buffer[SDCC_NAME_MAX];
          symbol * argsym = lval->sym;

          strncpyz (buffer, lval->sym->rname, sizeof(buffer));
          lval->sym = copySymbol (lval->sym);
          strncpyz (lval->sym->rname, buffer, sizeof(lval->sym->rname));

          strncpyz (lval->sym->name, buffer, sizeof(lval->sym->name));
          /* need to keep the original name for inlining to work */
          /*strncpyz (lval->name, buffer, sizeof(lval->name)); */

          addSym (SymbolTab, lval->sym, lval->sym->name,
                  lval->sym->level, lval->sym->block, 1);
          lval->sym->_isparm = 1;
          if (!isinSet (operKeyReset, lval->sym))
            {
              addSet(&operKeyReset, lval->sym);
            }

          /* restore the original symbol */
          lval->sym = argsym;
        }
    }
  return;
}
Esempio n. 5
0
/*-----------------------------------------------------------------*/
int
allocVariables (symbol * symChain)
{
  symbol *sym;
  symbol *csym;
  int stack = 0;
  int saveLevel = 0;

  /* go thru the symbol chain   */
  for (sym = symChain; sym; sym = sym->next)
    {
      /* if this is a typedef then add it */
      /* to the typedef table             */
      if (IS_TYPEDEF (sym->etype))
        {
          /* check if the typedef already exists    */
          csym = findSym (TypedefTab, NULL, sym->name);
          if (csym && csym->level == sym->level)
            werror (E_DUPLICATE_TYPEDEF, sym->name);

          SPEC_EXTR (sym->etype) = 0;
          addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
          continue;             /* go to the next one */
        }
      /* make sure it already exists */
      csym = findSymWithLevel (SymbolTab, sym);
      if (!csym || (csym && csym->level != sym->level))
        csym = sym;

      /* check the declaration */
      checkDecl (csym, 0);

      /* if this is a function or a pointer to a */
      /* function then do args processing        */
      if (funcInChain (csym->type))
        {
          processFuncArgs (csym);
        }

      /* if this is an extern variable then change */
      /* the level to zero temporarily             */
      if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
        {
          saveLevel = csym->level;
          csym->level = 0;
        }

      /* if this is a literal then it is an enumerated */
      /* type so need not allocate it space for it     */
      if (IS_LITERAL (sym->etype))
        continue;

      /* generate the actual declaration */
      if (csym->level)
        {
          allocLocal (csym);
          if (csym->onStack)
            stack += getSize (csym->type);
        }
      else
        allocGlobal (csym);

      /* restore the level */
      if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
        csym->level = saveLevel;
    }

  return stack;
}
Esempio n. 6
0
/* Read the symbols from the object/exe specified by the SegInfo into
   the tables within the supplied SegInfo.  */
static
void vg_read_lib_symbols ( SegInfo* si )
{
   Elf32_Ehdr*   ehdr;       /* The ELF header                          */
   Elf32_Shdr*   shdr;       /* The section table                       */
   UChar*        sh_strtab;  /* The section table's string table        */
   struct nlist* stab;       /* The .stab table                         */
   UChar*        stabstr;    /* The .stab string table                  */
   Int           stab_sz;    /* Size in bytes of the .stab table        */
   Int           stabstr_sz; /* Size in bytes of the .stab string table */
   Int           fd;
   Int           i;
   Bool          ok;
   Addr          oimage;
   Int           n_oimage;
   struct stat   stat_buf;

   /* for the .stabs reader */
   Int    curr_filenmoff;
   Addr   curr_fnbaseaddr;
   Addr   range_startAddr;
   Int    range_lineno;

   oimage = (Addr)NULL;
   if (VG_(clo_verbosity) > 1)
      VG_(message)(Vg_UserMsg, "Reading syms from %s", 
                               si->filename );

   /* mmap the object image aboard, so that we can read symbols and
      line number info out of it.  It will be munmapped immediately
      thereafter; it is only aboard transiently. */

   i = stat(si->filename, &stat_buf);
   if (i != 0) {
      vg_symerr("Can't stat .so/.exe (to determine its size)?!");
      return;
   }
   n_oimage = stat_buf.st_size;

   fd = VG_(open_read)(si->filename);
   if (fd == -1) {
      vg_symerr("Can't open .so/.exe to read symbols?!");
      return;
   }

   oimage = (Addr)VG_(mmap)( NULL, n_oimage, PROT_READ, MAP_PRIVATE, fd, 0 );
   if (oimage == ((Addr)(-1))) {
      VG_(message)(Vg_UserMsg,
                   "mmap failed on %s", si->filename );
      VG_(close)(fd);
      return;
   }

   VG_(close)(fd);

   /* Ok, the object image is safely in oimage[0 .. n_oimage-1]. 
      Now verify that it is a valid ELF .so or executable image.
   */
   ok = (n_oimage >= sizeof(Elf32_Ehdr));
   ehdr = (Elf32_Ehdr*)oimage;

   if (ok) {
      ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
             && ehdr->e_ident[EI_MAG1] == 'E'
             && ehdr->e_ident[EI_MAG2] == 'L'
             && ehdr->e_ident[EI_MAG3] == 'F');
      ok &= (ehdr->e_ident[EI_CLASS] == ELFCLASS32
             && ehdr->e_ident[EI_DATA] == ELFDATA2LSB
             && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
      ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
      ok &= (ehdr->e_machine == EM_386);
      ok &= (ehdr->e_version == EV_CURRENT);
      ok &= (ehdr->e_shstrndx != SHN_UNDEF);
      ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
   }

   if (!ok) {
      vg_symerr("Invalid ELF header, or missing stringtab/sectiontab.");
      VG_(munmap) ( (void*)oimage, n_oimage );
      return;
   }

   if (VG_(clo_trace_symtab))
      VG_(printf)( 
          "shoff = %d,  shnum = %d,  size = %d,  n_vg_oimage = %d\n",
          ehdr->e_shoff, ehdr->e_shnum, sizeof(Elf32_Shdr), n_oimage );

   if (ehdr->e_shoff + ehdr->e_shnum*sizeof(Elf32_Shdr) > n_oimage) {
      vg_symerr("ELF section header is beyond image end?!");
      VG_(munmap) ( (void*)oimage, n_oimage );
      return;
   }

   shdr = (Elf32_Shdr*)(oimage + ehdr->e_shoff);
   sh_strtab = (UChar*)(oimage + shdr[ehdr->e_shstrndx].sh_offset);

   /* try and read the object's symbol table */
   {
      UChar*     o_strtab    = NULL;
      Elf32_Sym* o_symtab    = NULL;
      UInt       o_strtab_sz = 0;
      UInt       o_symtab_sz = 0;

      UChar*     o_got = NULL;
      UChar*     o_plt = NULL;
      UInt       o_got_sz = 0;
      UInt       o_plt_sz = 0;

      Bool       snaffle_it;
      Addr       sym_addr;

      /* find the .stabstr and .stab sections */
      for (i = 0; i < ehdr->e_shnum; i++) {
         if (0 == VG_(strcmp)(".symtab",sh_strtab + shdr[i].sh_name)) {
            o_symtab    = (Elf32_Sym*)(oimage + shdr[i].sh_offset);
            o_symtab_sz = shdr[i].sh_size;
            vg_assert((o_symtab_sz % sizeof(Elf32_Sym)) == 0);
            /* check image overrun here */
         }
         if (0 == VG_(strcmp)(".strtab",sh_strtab + shdr[i].sh_name)) {
            o_strtab    = (UChar*)(oimage + shdr[i].sh_offset);
            o_strtab_sz = shdr[i].sh_size;
            /* check image overrun here */
         }

         /* find out where the .got and .plt sections will be in the
            executable image, not in the object image transiently loaded.
         */
         if (0 == VG_(strcmp)(".got",sh_strtab + shdr[i].sh_name)) {
            o_got    = (UChar*)(si->offset
                                + shdr[i].sh_offset);
            o_got_sz = shdr[i].sh_size;
            /* check image overrun here */
         }
         if (0 == VG_(strcmp)(".plt",sh_strtab + shdr[i].sh_name)) {
            o_plt    = (UChar*)(si->offset
                                + shdr[i].sh_offset);
            o_plt_sz = shdr[i].sh_size;
            /* check image overrun here */
         }

      }

      if (VG_(clo_trace_symtab)) {
         if (o_plt) VG_(printf)( "PLT: %p .. %p\n",
                                 o_plt, o_plt + o_plt_sz - 1 );
         if (o_got) VG_(printf)( "GOT: %p .. %p\n",
                                 o_got, o_got + o_got_sz - 1 );
      }

      if (o_strtab == NULL || o_symtab == NULL) {
         vg_symerr("   object doesn't have a symbol table");
      } else {
         /* Perhaps should start at i = 1; ELF docs suggest that entry
            0 always denotes `unknown symbol'. */
         for (i = 1; i < o_symtab_sz/sizeof(Elf32_Sym); i++){
#           if 0
            VG_(printf)("raw symbol: ");
            switch (ELF32_ST_BIND(o_symtab[i].st_info)) {
               case STB_LOCAL:  VG_(printf)("LOC "); break;
               case STB_GLOBAL: VG_(printf)("GLO "); break;
               case STB_WEAK:   VG_(printf)("WEA "); break;
               case STB_LOPROC: VG_(printf)("lop "); break;
               case STB_HIPROC: VG_(printf)("hip "); break;
               default:         VG_(printf)("??? "); break;
            }
            switch (ELF32_ST_TYPE(o_symtab[i].st_info)) {
               case STT_NOTYPE:  VG_(printf)("NOT "); break;
               case STT_OBJECT:  VG_(printf)("OBJ "); break;
               case STT_FUNC:    VG_(printf)("FUN "); break;
               case STT_SECTION: VG_(printf)("SEC "); break;
               case STT_FILE:    VG_(printf)("FIL "); break;
               case STT_LOPROC:  VG_(printf)("lop "); break;
               case STT_HIPROC:  VG_(printf)("hip "); break;
               default:          VG_(printf)("??? "); break;
            }
            VG_(printf)(
                ": value %p, size %d, name %s\n",
                si->offset+(UChar*)o_symtab[i].st_value,
                o_symtab[i].st_size,
                o_symtab[i].st_name 
                   ? ((Char*)o_strtab+o_symtab[i].st_name) 
                   : (Char*)"NONAME");                
#           endif

            /* Figure out if we're interested in the symbol.
               Firstly, is it of the right flavour? 
            */
            snaffle_it
               =  ( (ELF32_ST_BIND(o_symtab[i].st_info) == STB_GLOBAL ||
                     ELF32_ST_BIND(o_symtab[i].st_info) == STB_LOCAL /* ||
		     ELF32_ST_BIND(o_symtab[i].st_info) == STB_WEAK */)
                    &&
                    (ELF32_ST_TYPE(o_symtab[i].st_info) == STT_FUNC /*||
                     ELF32_ST_TYPE(o_symtab[i].st_info) == STT_OBJECT*/)
                  );

            /* Secondly, if it's apparently in a GOT or PLT, it's really
               a reference to a symbol defined elsewhere, so ignore it. 
            */
            sym_addr = si->offset
                       + (UInt)o_symtab[i].st_value;
            if (o_got != NULL
                && sym_addr >= (Addr)o_got 
                && sym_addr < (Addr)(o_got+o_got_sz)) {
               snaffle_it = False;
               if (VG_(clo_trace_symtab)) {
	          VG_(printf)( "in GOT: %s\n", 
                               o_strtab+o_symtab[i].st_name);
               }
            }
            if (o_plt != NULL
                && sym_addr >= (Addr)o_plt 
                && sym_addr < (Addr)(o_plt+o_plt_sz)) {
               snaffle_it = False;
               if (VG_(clo_trace_symtab)) {
	          VG_(printf)( "in PLT: %s\n", 
                               o_strtab+o_symtab[i].st_name);
               }
            }

            /* Don't bother if nameless, or zero-sized. */
            if (snaffle_it
                && (o_symtab[i].st_name == (Elf32_Word)NULL
                    || /* VG_(strlen)(o_strtab+o_symtab[i].st_name) == 0 */
                       /* equivalent but cheaper ... */
                       * ((UChar*)(o_strtab+o_symtab[i].st_name)) == 0
                    || o_symtab[i].st_size == 0)) {
               snaffle_it = False;
               if (VG_(clo_trace_symtab)) {
	          VG_(printf)( "size=0: %s\n", 
                               o_strtab+o_symtab[i].st_name);
               }
            }

#           if 0
            /* Avoid _dl_ junk.  (Why?) */
            /* 01-02-24: disabled until I find out if it really helps. */
            if (snaffle_it
                && (VG_(strncmp)("_dl_", o_strtab+o_symtab[i].st_name, 4) == 0
                    || VG_(strncmp)("_r_debug", 
                                   o_strtab+o_symtab[i].st_name, 8) == 0)) {
               snaffle_it = False;
               if (VG_(clo_trace_symtab)) {
                  VG_(printf)( "_dl_ junk: %s\n", 
                               o_strtab+o_symtab[i].st_name);
               }
            }
#           endif

            /* This seems to significantly reduce the number of junk
               symbols, and particularly reduces the number of
               overlapping address ranges.  Don't ask me why ... */
	    if (snaffle_it && (Int)o_symtab[i].st_value == 0) {
               snaffle_it = False;
               if (VG_(clo_trace_symtab)) {
                  VG_(printf)( "valu=0: %s\n", 
                               o_strtab+o_symtab[i].st_name);
               }
            }

	    /* If no part of the symbol falls within the mapped range,
               ignore it. */
            if (sym_addr+o_symtab[i].st_size <= si->start
                || sym_addr >= si->start+si->size) {
               snaffle_it = False;
	    }

            if (snaffle_it) {
               /* it's an interesting symbol; record ("snaffle") it. */
               RiSym sym;
               Char* t0 = o_symtab[i].st_name 
                             ? (Char*)(o_strtab+o_symtab[i].st_name) 
                             : (Char*)"NONAME";
               Int nmoff = addStr ( si, t0 );
               vg_assert(nmoff >= 0 
                         /* && 0==VG_(strcmp)(t0,&vg_strtab[nmoff]) */ );
               vg_assert( (Int)o_symtab[i].st_value >= 0);
               /* VG_(printf)("%p + %d:   %s\n", si->addr, 
                              (Int)o_symtab[i].st_value, t0 ); */
               sym.addr  = sym_addr;
               sym.size  = o_symtab[i].st_size;
               sym.nmoff = nmoff;
               addSym ( si, &sym );
	    }
         }
      }
   }

   /* Reading of the "stabs" debug format information, if any. */
   stabstr    = NULL;
   stab       = NULL;
   stabstr_sz = 0;
   stab_sz    = 0;
   /* find the .stabstr and .stab sections */
   for (i = 0; i < ehdr->e_shnum; i++) {
      if (0 == VG_(strcmp)(".stab",sh_strtab + shdr[i].sh_name)) {
         stab = (struct nlist *)(oimage + shdr[i].sh_offset);
         stab_sz = shdr[i].sh_size;
      }
      if (0 == VG_(strcmp)(".stabstr",sh_strtab + shdr[i].sh_name)) {
         stabstr = (UChar*)(oimage + shdr[i].sh_offset);
         stabstr_sz = shdr[i].sh_size;
      }
   }

   if (stab == NULL || stabstr == NULL) {
      vg_symerr("   object doesn't have any debug info");
      VG_(munmap) ( (void*)oimage, n_oimage );
      return;
   }

   if ( stab_sz + (UChar*)stab > n_oimage + (UChar*)oimage
        || stabstr_sz + (UChar*)stabstr 
           > n_oimage + (UChar*)oimage ) {
      vg_symerr("   ELF debug data is beyond image end?!");
      VG_(munmap) ( (void*)oimage, n_oimage );
      return;
   }

   /* Ok.  It all looks plausible.  Go on and read debug data. 
         stab kinds: 100   N_SO     a source file name
                      68   N_SLINE  a source line number
                      36   N_FUN ?  start of a function

      In this loop, we maintain a current file name, updated
      as N_SOs appear, and a current function base address,
      updated as N_FUNs appear.  Based on that, address ranges
      for N_SLINEs are calculated, and stuffed into the 
      line info table.

      N_SLINE indicates the start of a source line.  Functions are
      delimited by N_FUNS, at the start with a non-empty string and at
      the end with an empty string.  The latter facilitates detecting
      where to close the last N_SLINE for a function. 
   */
   curr_filenmoff  = addStr(si,"???");
   curr_fnbaseaddr = (Addr)NULL;
   range_startAddr = 0;
   range_lineno    = 0;

   for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) {
#     if 0
      VG_(printf) ( "   %2d  ", i );
      VG_(printf) ( "type=0x%x   othr=%d   desc=%d   value=0x%x   strx=%d  %s",
                    stab[i].n_type, stab[i].n_other, stab[i].n_desc, 
                    (int)stab[i].n_value,
                    (int)stab[i].n_un.n_strx, 
                    stabstr + stab[i].n_un.n_strx );
      VG_(printf)("\n");
#     endif

      switch (stab[i].n_type) {

         case 68: { /* N_SLINE */
            /* flush the current line, if any, and start a new one */
            Addr range_endAddr 
               = curr_fnbaseaddr 
                    + (UInt)stab[i].n_value - 1;
            if (range_startAddr != 0) {
               addLineInfo ( si,
                             curr_filenmoff,
                             range_startAddr,
                             range_endAddr,
                             range_lineno );
            }
            range_startAddr = range_endAddr + 1;
            range_lineno = stab[i].n_desc;              
            break;
         }

         case 36: { /* N_FUN */
            if ('\0' == * (stabstr + stab[i].n_un.n_strx) ) {
               /* N_FUN with no name -- indicates the end of a fn.
                  Flush the current line, if any, but don't start a
                  new one. */
               Addr range_endAddr 
                  = curr_fnbaseaddr 
                       + (UInt)stab[i].n_value - 1;
               if (range_startAddr != 0) {
                  addLineInfo ( si,
                                curr_filenmoff,
                                range_startAddr,
                                range_endAddr,
                                range_lineno );
               }
               range_startAddr = 0;
            } else {
               /* N_FUN with a name -- indicates the start of a fn.  */
               curr_fnbaseaddr = si->offset
                                 + (Addr)stab[i].n_value;
               range_startAddr = curr_fnbaseaddr;
            }
            break;
         }

         case 100: /* N_SO */
         case 132: /* N_SOL */
         /* seems to give lots of locations in header files */
         /* case 130: */ /* BINCL */
         { 
            UChar* nm = stabstr + stab[i].n_un.n_strx;
            UInt len = VG_(strlen)(nm);
            if (len > 0 && nm[len-1] != '/')
               curr_filenmoff = addStr ( si, nm );
            else
               if (len == 0)
                  curr_filenmoff = addStr ( si, "?1\0" );
            break;
         }

#        if 0
         case 162: /* EINCL */
            curr_filenmoff = addStr ( si, "?2\0" );
            break;
#        endif

         default:
            break;
      }
   } /* for (i = 0; i < stab_sz/(int)sizeof(struct nlist); i++) */

   /* Last, but not least, heave the oimage back overboard. */
   VG_(munmap) ( (void*)oimage, n_oimage );
}