Source file: /~heha/hsn/esptool.zip/elffile.cpp

//#include <stdio.h>	// _snprintf
//#include <string.h>	// strcmp
//#include <stdlib.h>	// getenv
#include "esptool.h"	// Fatal()
#include "elffile.h"
#include <io.h>		// mktemp - igitt!!

ELFFile::ELFFile(const char*n):name(n),symbols(0),nsym(0) {}

bool ELFFile::valid(byte*fdata,uint32 fsize) {
 return fsize>=32 && reinterpret_cast<HDR*>(fdata)->magic==MAGIC;
}

bool ELFFile::parse(Dumpfile&df,cb2_t cb,void*cbd,uint32*sadr) {
 HDR&e=*(HDR*)df.data();
 if (sadr) *sadr=e.entry;
 for (int i=0; i<e.phnum; i++) {
  ProgHdr32&ph=*(ProgHdr32*)(df.data()+e.phoff+i*e.phentsize);
  if (ph.type==1 && ph.filesz) {
   Dumpfile sub(df.data()+ph.offset,ph.filesz,ph.paddr);
   if (!cb(cbd,sub)) return 0;
  }
 }
 return true;
}

bool ELFFile::is_lx106() {
 return !strcmp(getenv("XTENSA_CORE"),"lx106");
}

void ELFFile::add_sym(const char*n,uint32 v) {
 uint32 k=nsym;
 symbols=(SYM*)realloc(symbols,++nsym*sizeof*symbols);
 symbols[k].name=_strdup(n);
 symbols[k].value=v;
}

void ELFFile::_fetch_symbols() {
 if (symbols) return;
 const char*tool_nm = is_lx106() ? "xt-nm" : "xtensa-lx106-elf-nm";
 char s[256];
 _snprintf(s,sizeof s,"%s \"%s\"",tool_nm,name);
 FILE*proc = _popen(s,"rb");
 if (!proc) Fatal("Error calling %s, do you have Xtensa toolchain in PATH?", tool_nm);
 char line[260];
 while (fgets(line,sizeof line,proc)) {
  char*p=line; while (strchr(" \t",*p)) ++p;	// TrimLeft
  char f0[32],f1[32];
  if (sscanf(p,"%32s %32s",f0,f1)==2) {
   if (f0[0]=='U') {
    printf("Warning: ELF binary has undefined symbol %s\n",f1);
    continue;
   }
   add_sym(f1,strtoul(f0,0,0));
  }
 }
//            except ValueError:
//                Fatal("Failed to strip symbol output from nm: %s", fields);
}

uint32 ELFFile::get_symbol_addr(const char*sym) {
 _fetch_symbols();
 for (uint32 i=0; i<nsym; i++) if (!strcmp(sym,symbols[i].name)) return symbols[i].value;
 return (uint32)-1;
}

uint32 ELFFile::get_entry_point() {
 const char*tool_readelf = is_lx106() ? "xt-readelf" : "xtensa-lx106-elf-readelf";
 char s[256];
 _snprintf(s,sizeof s,"%s -h \"%s\"",tool_readelf,name);
 FILE*proc = _popen(s,"rb");
 if (!proc) Fatal("Error calling %s, do you have Xtensa toolchain in PATH?",tool_readelf);
 char line[260];
 while (fgets(line,sizeof line,proc)) {
  char*p=line; while (strchr(" \t",*p)) ++p;	// TrimLeft
  uint32 e;
  if (sscanf(p,"Entry %u",&e)==1) {
   fclose(proc);
   return e;
  }
 }
 fclose(proc);
 return (uint32)-1;
}

bool ELFFile::load_section_cb(void*cbd,const Dumpfile&df) {
 return true;
}

bool ELFFile::load_section(const void*section,const void*&data) {
 const char*tool_objcopy = is_lx106() ? "xt-objcopy" : "xtensa-lx106-elf-objcopy";
 const char*tmpsection = _mktemp("sec");
 char s[256];
 _snprintf(s,sizeof s,"%s --only-section %s -Obinary \"%s\" %s",tool_objcopy,section,name,tmpsection);
 FILE*proc = _popen(s,"rb");
 char line[260];
 while (fgets(line,sizeof line,proc));	// warten bis fertig und stdout absaugen
 fclose(proc);
 bool ok=parseBinFile(tmpsection,load_section_cb,&data,0);
 remove(tmpsection);
 return ok;
}

ELFFile::~ELFFile() {
 if (!symbols) return;
 for (unsigned i=0; i<nsym; i++) free(const_cast<char*>(symbols[i].name));
 delete[] symbols;
}
Detected encoding: ASCII (7 bit)2