/*---------------------------------------------------------------------------*
  Project:  TwlSDK - stripdebug
  File:     stripdebug.c

  Copyright 2006-2008 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Date:: 2008-09-17#$
  $Rev: 8556 $
  $Author: okubata_ryoma $
 *---------------------------------------------------------------------------*/
#include    <stdio.h>
#include    <stdlib.h>              // atoi()
#include    <ctype.h>
#include    <getopt.h>              // getopt()
#include    <string.h>
#include    "types.h"
#include    "elf.h"
#include    "elf_loader.h"
#include    "searcharg.h"


#define    DS_ROM_HEADER_SIZE    0x4000

char*      input_elf_fname    = NULL;
char*      stripped_elf_fname = NULL;
char*      added_elf_fname    = NULL;
char       c_source_line_str[256];

#define    STRIPPED_ELF_FILENAME    "stripped-"
#define    ADDED_ELF_FILENAME       "added-"
FILE*      NewElfFilep;

/*---------------------------------------------------------------------------*
 *  
 *---------------------------------------------------------------------------*/
u32 adr_ALIGN( u32 addr, u32 align_size);
void file_write( char* c_str, FILE* Fp);


/*---------------------------------------------------------------------------*
 *  
 *---------------------------------------------------------------------------*/
u16        dbg_print_flag;
u16        unresolved_table_block_flag = 0;

/*---------------------------------------------------------------------------*
 *  MAIN
 *---------------------------------------------------------------------------*/

int main(int argc, char *argv[])
{
    FILE        *FHp;
    u32*        newelfbuf;
#if (SPECIAL_SECTION_ENABLE == 1) /*特殊セクション追加*/
    u32*        dbgelfbuf;
#endif
//    u32*        aligned_newelfbuf;
    u32         elfsize;
    ELHandle    ElfH, ElfH2;
    char*       elf_filename;
    u32         elf_namesize;
    char*       slash_pointer;
    u16         result;
    

/*    
    for( i=0; i<argc; i++) {
        fprintf(stdout, "%s\n", argv[i]);
    }
*/

    /*-----------------------------------------------------*/
    dbg_print_flag = 0;
    SA_searchopt( argc, argv);

    EL_Init();
    unresolved_table_block_flag = 0;    //Unresolvedテーブルへの追加禁止を解除

    /* dllファイルを調べる */
    FHp = fopen( input_elf_fname, "rb");
    if( FHp == NULL) {
        printf( "cannot open file \"%s\".\n", input_elf_fname);
        exit( 1);
    }
    fseek( FHp, 0, SEEK_END);
    elfsize = ftell( FHp);
    fseek( FHp, 0, SEEK_SET);
    
    printf( "input elf size    = 0x%x\n", (int)elfsize);
    
    EL_InitHandle( &ElfH);
    EL_InitHandle( &ElfH2);
  
//    aligned_newelfbuf = (((u32)newelfbuf) & (~0x20)) + 0x20; //0x20バイトアライン
    newelfbuf = (u32*)malloc( elfsize);
    result = EL_LoadLibraryfromFile( &ElfH,  FHp, newelfbuf, 0);
  
#if (SPECIAL_SECTION_ENABLE == 1) /*特殊セクション追加*/
    dbgelfbuf = (u32*)malloc( elfsize * 2);
    result = EL_LoadLibraryfromFile( &ElfH2,  FHp, dbgelfbuf, 1);
#endif
  
    fclose( FHp);
//    EL_ResolveAllLibrary();

  
    /*---------------------------------------------*/
    /*-o オプションがあれば指定ファイル名に変更*/
    if( stripped_elf_fname != NULL) {
        elf_filename = stripped_elf_fname;
    }else{
        /*elfファイル名生成*/
        elf_namesize = strlen( STRIPPED_ELF_FILENAME) + strlen( input_elf_fname) + 1;//+1は最後のnull文字
        elf_filename = malloc( elf_namesize);
        memset( elf_filename, 0, elf_namesize);
    
        slash_pointer = strrchr( input_elf_fname, '/');
        if( slash_pointer == NULL) {                      //スラッシュがない場合
            strcpy( elf_filename, STRIPPED_ELF_FILENAME); //接頭語
            strcat( elf_filename, input_elf_fname);       //ファイル名
        }else{                                            //スラッシュがある場合
            memcpy( elf_filename, input_elf_fname, (slash_pointer - input_elf_fname)+1);
            strcat( elf_filename, STRIPPED_ELF_FILENAME);
            strcat( elf_filename, slash_pointer+1);
        }
    }
    
    NewElfFilep = fopen( elf_filename, "wb");
    if( !NewElfFilep) {
        printf( "error : cannot create file \"%s\".\n\n", elf_filename);
        exit( 1);
    }

    printf( "stripped elf size = 0x%x\n", (int)(ElfH.newelf_size));
    fwrite( newelfbuf, 1, ElfH.newelf_size, NewElfFilep);
  
    fclose( NewElfFilep);
    free( newelfbuf);
    printf( "stripped elf file \"%s\" is generated.\n\n", elf_filename);
    if( stripped_elf_fname == NULL) {    //-o オプションがなければmallocしているので開放
        free( elf_filename);
    }
    /*---------------------------------------------*/

  

    /*---------------------------------------------*/
#if (SPECIAL_SECTION_ENABLE == 1) /*特殊セクション追加*/
    /*-O オプションがあれば指定ファイル名に変更*/
    if( added_elf_fname != NULL) {
        elf_filename = added_elf_fname;
    }else{
        /*elfファイル名生成*/
        elf_namesize = strlen( ADDED_ELF_FILENAME) + strlen( input_elf_fname) + 1;//+1は最後のnull文字
        elf_filename = malloc( elf_namesize);
        memset( elf_filename, 0, elf_namesize);
    
        slash_pointer = strrchr( input_elf_fname, '/');
        if( slash_pointer == NULL) {                      //スラッシュがない場合
            strcpy( elf_filename, ADDED_ELF_FILENAME);    //接頭語
            strcat( elf_filename, input_elf_fname);       //ファイル名
        }else{                                            //スラッシュがある場合
            memcpy( elf_filename, input_elf_fname, (slash_pointer - input_elf_fname)+1);
            strcat( elf_filename, ADDED_ELF_FILENAME);
            strcat( elf_filename, slash_pointer+1);
        }
    }
    
    NewElfFilep = fopen( elf_filename, "wb");
    if( !NewElfFilep) {
        printf( "error : cannot create file \"%s\".\n\n", elf_filename);
        exit( 1);
    }

    printf( "added elf size = 0x%x\n", (int)(ElfH2.newelf_size));
    fwrite( dbgelfbuf, 1, ElfH2.newelf_size, NewElfFilep);
    
    fclose( NewElfFilep);
    free( dbgelfbuf);
    printf( "added elf file \"%s\" is generated.\n\n", elf_filename);
    if( added_elf_fname == NULL) {    //-o オプションがなければmallocしているので開放
        free( elf_filename);
    }
#endif
    /*---------------------------------------------*/
  
    exit( 0);

    /*-----------------------------------------------------*/
    
    return 0;
}

/*---------------------------------------------------------------------------*
 *  アドレスのアラインメント
 *---------------------------------------------------------------------------*/
u32 adr_ALIGN( u32 addr, u32 align_size)
{
    u32 aligned_addr;
    
    if( (addr % align_size) == 0) {
        aligned_addr = addr;
    }else{
        aligned_addr = (((addr) & ~((align_size) - 1)) + (align_size));
    }
    
    return aligned_addr;
}

/*---------------------------------------------------------------------------*
 *  ファイルに文字列を書き込み
 *---------------------------------------------------------------------------*/
void file_write( char* c_str, FILE* Fp)
{
    fwrite( c_str, 1, strlen( c_str), Fp);
}
