/*## (c) SECURITY EXPLORATIONS    2018 poland                                #*/
/*##     http://www.security-explorations.com                                #*/

/* THIS SOFTWARE IS PROTECTED BY DOMESTIC AND INTERNATIONAL COPYRIGHT LAWS    */
/* UNAUTHORISED COPYING OF THIS SOFTWARE IN EITHER SOURCE OR BINARY FORM IS   */
/* EXPRESSLY FORBIDDEN. ANY USE, INCLUDING THE REPRODUCTION, MODIFICATION,    */
/* DISTRIBUTION, TRANSMISSION, RE-PUBLICATION, STORAGE OR DISPLAY OF ANY      */
/* PART OF THE SOFTWARE, FOR COMMERCIAL OR ANY OTHER PURPOSES REQUIRES A      */
/* VALID LICENSE FROM THE COPYRIGHT HOLDER.                                   */

/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS    */
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,*/
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    */
/* SECURITY EXPLORATIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF  */
/* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE     */
/* SOFTWARE.                                                                  */

import java.lang.*;
import java.io.*;
import java.util.*;

public class KSyms {
 public static class SysFileInputStream extends InputStream {
  int pos;
  int bufcnt;
  int buf;
  int fd;

  public SysFileInputStream(String name) {
   super();

   pos=bufcnt=0;

   fd=Syscall.open(name,FSDefs.O_RDONLY);

   if (fd>0) {
    NativeCode nc=NativeCode.getInstance();
    buf=nc.malloc(BUFSIZE);
   }
  }

  public int read() throws IOException {
   int val=-1;

   if (fd>0) {
    if (bufcnt==0) {
     bufcnt=Syscall.read(fd,buf,BUFSIZE);    
     if (bufcnt<=0) return -1;
     pos=0;
    }

    val=Memory.read_byte(buf+pos);
    pos++;
    bufcnt--;
   }

   return val;
  }

  public void close() throws IOException {
   if (fd>0) {
    Syscall.close(fd);

    NativeCode nc=NativeCode.getInstance();
    nc.free(buf);

    fd=-1;
   }
  }
 }

 public static final String KALLSYMS   = "/proc/kallsyms";

 public static final String sym_prefixes[]={
  "sys_",
  "stptiHAL_read_proc"
 };

 public static final int BUFSIZE=0x2000;

 private static Hashtable syms;

 private static boolean store_symbol(String sname) {
  boolean res=false;

  for(int i=0;i<sym_prefixes.length;i++) {
   if (sname.startsWith(sym_prefixes[i])) {
    res=true;
    break;
   }
  }

  return res;
 }

 private static void parse_line(String line) {
  String sname=null;
  int saddr=0;

  int idx=line.indexOf(' ');
  if (idx>0) {
   String s=line.substring(0,idx);
   saddr=Utils.parse_hex(s);

   s=line.substring(idx+3,line.length());

   idx=s.indexOf(' ');
   if (idx>0) {
    s=s.substring(0,idx);    
   }

   idx=s.indexOf('\t');
   if (idx>0) {
    s=s.substring(0,idx);    
   }

   sname=s;

   if (store_symbol(sname)) {
    syms.put(sname,new Integer(saddr));
   }
  }
 }

 private static void parse_symbols() {
  try {
   SysFileInputStream sfis=new SysFileInputStream(KALLSYMS);
   BufferedReader b=new BufferedReader(new InputStreamReader(sfis,"utf-8"));

   String line=b.readLine();

   while(line!=null) {
    parse_line(line);
    line=b.readLine();
   }

   b.close();
   sfis.close();
  } catch(Throwable t) {}
 }

 static {
  syms=new Hashtable();
  parse_symbols();
 }

 public static int sym_addr(String name) {
  Integer val=(Integer)syms.get(name);

  if (val!=null) {
   return val.intValue();
  }

  return 0;
 }

}
