Ejemplo n.º 1
0
//--------------------------------------------------------------------------
static void load_subspaces(linput_t *li, header &h, long fpos, int n)
{
  if ( !n ) return;
  char buf[MAXSTR];
  for ( int i=0; i < n; i++ )
  {
    subspace_dictionary_record sr;
    qlseek(li, fpos + i*sizeof(sr));
    lread(li, &sr, sizeof(sr));
    sr.swap();

    if ( !sr.is_loadable() || !sr.subspace_length ) continue;
    if ( sr.fixup_request_quantity ) complain_fixup();
    ea_t start = sr.subspace_start;
    ea_t end = start + sr.initialization_length;
    file2base(li, sr.file_loc_init_value, start, end, FILEREG_PATCHABLE);
    end = start + sr.subspace_length;
    char *name = get_space_name(li, h, sr.name.n_strx, buf, sizeof(buf));
    set_selector(i, 0);
    const char *sclass = strstr(name, "CODE") ? CLASS_CODE : CLASS_DATA;
    add_segm(i, start, end, name, sclass);

    if ( i == first_text_subspace_idx )
      first_text_subspace_fpos = sr.file_loc_init_value;
//    sr.alignment,
  }
}
Ejemplo n.º 2
0
//----------------------------------------------------------------------
//
//      loads a 512 byte trainer (located at file offset INES_HDR_SIZE)
//      to TRAINER_START_ADDRESS
//
static void load_trainer( linput_t *li )
{
    if( !INES_MASK_SRAM( hdr.rom_control_byte_0 ) )
    {
        bool success = add_segm( 0, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, "TRAINER", CLASS_CODE ) == 1;
        msg("creating TRAINER segment..%s", success ? "ok!\n" : "failure!\n");
        set_segm_addressing( getseg( TRAINER_START_ADDRESS ), 0 );
    }
    file2base(li, INES_HDR_SIZE, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, FILEREG_PATCHABLE);
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------
static void read_text(linput_t *li)
{
  text txt;
  const int size = offsetof(text, segment);
  lread(li, &txt, size);
  if ( txt.length != 0 )
  {
    uint32 fptr = qltell(li);
    ea_t sea = getsea(txt.txt_IN);
    if ( sea != BADADDR )
    {
      sea += txt.txt_offset;
      file2base(li, fptr, sea, sea+txt.length, FILEREG_PATCHABLE);
    }
    qlseek(li, fptr+txt.length);
  }
}
Ejemplo n.º 4
0
//----------------------------------------------------------------------
//
//      load 8k prg rom bank into database
//
static void load_8k_prg_rom_bank( linput_t *li, uchar banknr, ea_t address )
{

    if( (banknr == 0) || (hdr.prg_page_count_16k == 0) )
        return;

    // this is the file offset to begin reading pages from
    long offset = INES_HDR_SIZE +
        (INES_MASK_TRAINER(hdr.rom_control_byte_0) ? TRAINER_SIZE : 0) +
        (banknr - 1) * PRG_ROM_8K_BANK_SIZE;
    
    // load page from ROM file into segment
    msg("mapping 8k PRG-ROM page %02d to %08x-%08x (file offset %08x) ..", 1, address, address + PRG_ROM_8K_BANK_SIZE, offset);
    if( file2base(li, offset, address, address + PRG_ROM_8K_BANK_SIZE, FILEREG_PATCHABLE) == 1)
        msg("ok\n");
    else
        msg("failure (corrupt ROM image?)\n");                  
}
Ejemplo n.º 5
0
//----------------------------------------------------------------------------
static bool map_psram(linput_t *li, uint32 psram_start_in_file)
{
  bool succeeded = false;

  segment_t s;
  s.startEA = 0x00000;
  s.endEA   = 0x10000;
  s.sel     = allocate_selector(s.startEA >> 4);

  if ( !file2base(li, psram_start_in_file, s.startEA, s.endEA, FILEREG_PATCHABLE) )
    loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", psram_start_in_file, s.startEA, s.endEA);

  succeeded = add_segm(s.sel, s.startEA, s.endEA, "RAM", NULL);
  if ( succeeded )
    succeeded = true;
  else
    loader_failure("Failed adding RAM segment\n");

  return succeeded;
}
Ejemplo n.º 6
0
//----------------------------------------------------------------------
//
//      load 8k chr rom bank into database
//
static void load_chr_rom_bank( linput_t *li, uchar banknr, ea_t address )
{
    // todo: add support for PPU
    // this function currently is disabled, since no
    // segment for the PPU is created
    msg("The loader was trying to load a CHR bank but the PPU is not supported yet.\n");
    return;

    if( (banknr == 0) || (hdr.chr_page_count_8k == 0) )
        return;
    
    // this is the file offset to begin reading pages from
    long offset = INES_HDR_SIZE +
        (INES_MASK_TRAINER(hdr.rom_control_byte_0) ? TRAINER_SIZE : 0) +
        PRG_PAGE_SIZE * hdr.prg_page_count_16k + (banknr - 1) * CHR_ROM_BANK_SIZE;
    
    // load page from ROM file into segment
    msg("mapping CHR-ROM page %02d to %08x-%08x (file offset %08x) ..", banknr, address, address + CHR_PAGE_SIZE, offset);
    if( file2base(li, offset, address, address + CHR_ROM_BANK_SIZE, FILEREG_PATCHABLE) == 1)
        msg("ok\n");
    else
        msg("failure (corrupt ROM image?)\n");
}
Ejemplo n.º 7
0
/*
 * this is where we finally load the file and create segments and other processing
 */
void idaapi
load_file(linput_t *li, ushort neflags, const char *fileformatname)
{
    /* reset file position to 0 - accept_file changed it? */
    qlseek(li, 0);
    /* add header structures */
    add_types();
    create_filename_cmt();
    /* process header and create its own segment */
    EFI_IMAGE_TE_HEADER teHeader = {0};
    if (qlread(li, &teHeader, sizeof(EFI_IMAGE_TE_HEADER)) != sizeof(EFI_IMAGE_TE_HEADER))
    {
        warning("Failed to read TE header\n");
        return;
    }
    /* read the data to the database */
    /* header starts at 0 */
    ea_t delta = teHeader.StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
    ea_t header_start = teHeader.ImageBase - delta;
    /* header total size is the TE header plus all sections that follow */
    ea_t header_end = teHeader.ImageBase - delta + sizeof(EFI_IMAGE_TE_HEADER) + teHeader.NumberOfSections * sizeof(EFI_IMAGE_SECTION_HEADER);
#if 1
    msg("Header start: 0x%llx\n", header_start);
    msg("Header end: 0x%llx\n", header_end);
    msg("Delta: 0x%llx\n", delta);
#endif
    file2base(li, 0, header_start, header_end, 1);
    /* create the HEADER segment */
    add_segm(0, header_start, header_end, "HEADER", "DATA");
    /* set header structures */
    doStruct(teHeader.ImageBase - delta, sizeof(EFI_IMAGE_TE_HEADER), efi_image_te_header_struct);
    for (uint8_t i = 0; i < teHeader.NumberOfSections; i++)
    {
        doStruct(teHeader.ImageBase - delta + sizeof(EFI_IMAGE_TE_HEADER) + i * sizeof(EFI_IMAGE_SECTION_HEADER), sizeof(EFI_IMAGE_SECTION_HEADER), efi_image_section_header_struct);
    }
    
    int headerPosition = sizeof(EFI_IMAGE_TE_HEADER);

    /* read sections */
    for (uint8_t i = 0; i < teHeader.NumberOfSections; i++)
    {
        qlseek(li, headerPosition);
        EFI_IMAGE_SECTION_HEADER sectionHeader = {0};
        qlread(li, &sectionHeader, sizeof(EFI_IMAGE_SECTION_HEADER));
        msg("Section name: %s\n", sectionHeader.Name);
        /* ok */
        uint32_t position = sectionHeader.PointerToRawData - delta;
        msg("Position %x\n", position);
        qlseek(li, position);
        ea_t section_start = sectionHeader.VirtualAddress + teHeader.ImageBase - delta;
        ea_t section_end = 0;
        if (sectionHeader.Misc.VirtualSize > sectionHeader.SizeOfRawData)
        {
            section_end = sectionHeader.VirtualAddress + teHeader.ImageBase - delta + sectionHeader.Misc.VirtualSize;
        }
        else
        {
            section_end = sectionHeader.VirtualAddress + teHeader.ImageBase - delta + sectionHeader.SizeOfRawData;
        }
        msg("Section start: 0x%llx\n", section_start);
        msg("Section end: 0x%llx\n", section_end);
        file2base(li, position, section_start, section_end, 1);
        int bitness = -1;
        switch (teHeader.Machine) {
            case IMAGE_FILE_MACHINE_I386:
                bitness = 1;
                break;
            case IMAGE_FILE_MACHINE_X64:
                bitness = 2;
                break;
            default:
                bitness = 0;
        }
        const char *classType;
        if (qstrcmp((const char*)sectionHeader.Name, ".text") == 0)
        {
            classType = "CODE";
        }
        else
        {
            classType = "DATA";
        }
        add_segm(0, section_start, section_end, (const char*)sectionHeader.Name, classType);
        set_segm_addressing(get_segm_by_name((const char *)sectionHeader.Name), bitness);

        /* try to find the GUIDs in data section */
        if (qstrcmp((const char *)sectionHeader.Name, ".data") == 0)
        {
            find_guids(section_start, section_end);
        }

        /* advance to next section */
        headerPosition += sizeof(EFI_IMAGE_SECTION_HEADER);
    }
    /* configure the entrypoint address */
    add_entry(teHeader.AddressOfEntryPoint + teHeader.ImageBase - delta, teHeader.AddressOfEntryPoint + teHeader.ImageBase - delta, "_start", 1);

    /* all done */
}
Ejemplo n.º 8
0
//-----------------------------------------------------------------------------
// process a file record according to its "record_type".
// return true if there is no more records to process.
static bool process_record(linput_t *li, const uchar record_type, bool load) {
    bool finished = false;

    switch (record_type) {

        // A record with a header byte of $81 is a record that may contain code or
        // data from arbitrary segments.
        //
        // header      : 1 byte
        // segment     : 1 byte
        // gran        : 1 byte
        // start_addr  : 4 bytes (entry point)
        // length      : 2 bytes
        // data        : length bytes
        case 0x81:
            {
                mas_header_t header;
                memset(&header, 0, sizeof header);

                // read the header
                if (qlread(li, &header, sizeof header) != sizeof header)
                    mas_error("unable to read header (%d bytes)", sizeof header);

                // granularities that differ from 1 are rare and mostly appear
                // in DSP CPU's that are not designed for byte processing.
                if (header.gran != 1)
                    mas_error("unsupported granularity (%d)", header.gran);

                // set processor
                if (!mas_set_cpu(header.header))
                    mas_error("processor type '0x%X' is currently unsupported",
                        header.header);
                if (!load) // we have the processor, nothing else to do
                {
                  finished = true;
                  break;
                }

                // get segment name
                const char *segname = mas_get_segname(header.segment);
                if (segname == NULL)
                    mas_error("invalid segment '0x%X'", header.segment);

#if defined(DEBUG)
                msg("MAS: ready to read %d bytes (0x%X -> 0x%X)\n",
                    header.length, header.start_addr, header.start_addr + header.length);
#endif

                // send code in the database
                file2base(li, qltell(li), header.start_addr,
                    header.start_addr + header.length,
                    FILEREG_PATCHABLE);

                // set selector
                sel_t selector = allocate_selector(0);

                // create segment
                add_segm(selector, header.start_addr, header.start_addr + header.length,
                           segname, segname);
            }
            break;

        // The last record in a file bears the Header $00 and has only a string as
        // data field. This string does not have an explicit length specification;
        // its end is equal to the file's end.
        //
        // The string contains only the name of the program that created the file
        // and has no further meaning.
        //
        // creator     : x bytes
        case 0x00:
            {
                ulong length = qlsize(li) - qltell(li);
#if defined(DEBUG)
                msg("MAS: creator length : %ld bytes\n", length);
#endif
                if (length >= sizeof creator)
                    mas_error("creator length is too large (%ld >= %ld",
                        length, sizeof creator);
                int tmp;
                if ((tmp = qlread(li, creator, length)) != length)
                    mas_error("unable to read creator string (i read %d)", tmp);
                creator[tmp] = '\0';
            }
            finished = true;
            break;

        // entry_point : 4 bytes
        case 0x80:
            {
                if (qlread(li, &entry_point, 4) != 4)
                    mas_error("unable to read entry_point");
                if (load)
                {
#if defined(DEBUG)
                  msg("MAS: detected entry point : 0x%X\n", entry_point);
#endif
                  inf.startIP = entry_point;      // entry point
                  segment_t *s = getseg(entry_point);
                  inf.start_cs = s ? s->sel : 0;  // selector of code
                }
            }
            break;

        default:
            // start_addr  : 4 bytes
            // length      : 2 bytes
            // data        : length bytes
            if (record_type >= 0x01 && record_type <= 0x7F) {
                struct header {
                    int start_addr;
                    short length;
                } header;

                memset(&header, 0, sizeof header);

                // read the header
                if (qlread(li, &header, sizeof header) != sizeof header)
                    mas_error("unable to read header (%d bytes)", sizeof header);

                if (load)
                {
                  // send code in the database
                  file2base(li, qltell(li), header.start_addr,
                      header.start_addr + header.length,
                      FILEREG_PATCHABLE);

#if defined(DEBUG)
                  msg("MAS: i've read %d DATA bytes (0x%X -> 0x%X)\n",
                      header.length, header.start_addr, header.start_addr + header.length);
#endif

                  // set selector
                  sel_t selector = allocate_selector(0);

                  // create data segment
                  add_segm(selector, header.start_addr, header.start_addr + header.length,
                           "DATA", "DATA");
                }
                else
                  qlseek(li, qltell(li)+header.length);
            }
            else
                mas_error("invalid record type '0x%X'\n", record_type);
    }

    return finished;
}
Ejemplo n.º 9
0
//--------------------------------------------------------------------------
//
//      load file into the database.
//
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
{
//  int i;
  aif_header_t hd;
  if ( ph.id != PLFM_ARM )
    set_processor_type("arm", SETPROC_ALL|SETPROC_FATAL);
  lread(li,&hd,sizeof(hd));
  mf = uchar(match_zero_code(hd) - 1);
  if ( (hd.address_mode & 0xFF) != 32 )
  {
    if ( (hd.address_mode & 0xFF) != 0 )
      loader_failure("26-bit modules are not supported");
    msg("Old AIF format file...");
  }
  if ( hd.decompress_code != NOP )
    loader_failure("Compressed modules are not supported");
  if ( hd.self_reloc_code != NOP )
    loader_failure("Self-relocating modules are not supported");

  inf.baseaddr = 0;
  int isexec = is_bl(hd.entry_point);
  uint32 offset = sizeof(aif_header_t);
  uint32 start = hd.image_base;
  if ( isexec ) {
    start += sizeof(aif_header_t);
    hd.readonly_size -= sizeof(aif_header_t);
  }
  uint32 end = start + hd.readonly_size;
  file2base(li, offset, start, end, FILEREG_PATCHABLE);
  offset += hd.readonly_size;
  create_section(1, start, end, NAME_CODE, CLASS_CODE);
  if ( hd.readwrite_size != 0 ) {
    start = (hd.address_mode & AIF_SEP_DATA) ? hd.data_base : end;
    end = start + hd.readwrite_size;
    file2base(li, offset, start, end, FILEREG_PATCHABLE);
    offset += hd.readwrite_size;
    create_section(2, start, end, NAME_DATA, CLASS_DATA);
  }
  if ( hd.zero_init_size != 0 ) {
    start = end;
    end = start + hd.zero_init_size;
    create_section(3, start, end, NAME_BSS, CLASS_BSS);
  }
  create_filename_cmt();

  if ( isexec )
    hd.entry_point = hd.image_base
                   + offsetof(aif_header_t,entry_point)
                   + ((hd.entry_point & ~BLMASK) << 2)
                   + 8;
  inf.start_cs = 1;
  inf.startIP  = hd.entry_point;
  inf.beginEA  = hd.entry_point;

  if ( hd.debug_size != 0 ) {
    msg("Debugging information is present (%u bytes at file offset 0x%X)...\n",
                                                        hd.debug_size, offset);
    uchar *di = qalloc_array<uchar>(size_t(hd.debug_size));
    if ( di == NULL )
      nomem("AIF debugging info");
    qlseek(li,offset);
    lread(li, di, size_t(hd.debug_size));
    uchar *ptr = di;
    uchar *end = di + size_t(hd.debug_size);
    section_t *sect = NULL;
    while ( ptr < end )
    {
      size_t len = process_item(ptr, end-ptr, sect);
      if ( len == 0 )
      {
        warning("Corrupted debug info.");
        break;
      }
      ptr += len;
    }
    qfree(di);
  }

}