////////////////////////////////
// Win32 Implementation: SelfImg

#if OS_WINDOWS

# include "exefmt/pe/mr4th_pe.h"

MR4TH_SYMBOL_STATIC PE_SectionHeader*
pe_section_header_from_name(String8 img, String8 name){
    // extract dos header
    PE_DosHeader *dos_header = 0;
    if (sizeof(*dos_header) <= img.size){
        dos_header = (PE_DosHeader*)(img.str);
        if (dos_header->magic != PE_MSDOS_MAGIC){
            dos_header = 0;
        }
    }
    
    // extract coff file offset
    U32 coff_file_offset = 0;
    if (dos_header != 0){
        coff_file_offset = dos_header->coff_file_offset;
    }
    
    // extract pe signature
    U32 pe_signature = 0;
    U32 coff_header_offset = 0;
    if (0 < coff_file_offset &&
        coff_file_offset + sizeof(pe_signature) <= img.size){
        pe_signature = *(U32*)(img.str + coff_file_offset);
        if (pe_signature == PE_SIGNATURE){
            coff_header_offset = coff_file_offset + sizeof(pe_signature);
        }
    }
    
    // extract coff header
    PE_CoffHeader *coff_header = 0;
    if (0 < coff_header_offset &&
        coff_header_offset + sizeof(*coff_header) <= img.size){
        coff_header = (PE_CoffHeader*)(img.str + coff_header_offset);
    }
    
    // extract section table offset & count
    U32 section_table_offset = 0;
    U32 section_count = 0;
    if (coff_header != 0){
        section_table_offset = (  coff_header_offset
                                + sizeof(*coff_header)
                                + coff_header->optional_header_size);
        section_count = coff_header->section_count;
    }
    
    // scan section table
    PE_SectionHeader *match = 0;
    if (0 < section_table_offset &&
        section_table_offset + sizeof(PE_SectionHeader)*section_count <= img.size){
        PE_SectionHeader *sec = (PE_SectionHeader*)(img.str + section_table_offset);
        for (U32 i = 0; i < section_count; i += 1, sec += 1){
            String8 secname = str8_cstring_capped(sec->name, sec->name + sizeof(sec->name));
            if (str8_match(name, secname, 0)){
                match = sec;
                break;
            }
        }
    }
    
    return(match);
}

MR4TH_SYMBOL_STATIC SELFIMG_Section
selfimg_get_section_by_name(OS_VRange img, String8 name){
    String8 img_data = {(U8*)img.addr, img.size};
    SELFIMG_Section result = {0};
    PE_SectionHeader *section = pe_section_header_from_name(img_data, name);
    if (section != 0){
        result.offset = section->voff;
        result.size   = section->vsize;
    }
    return(result);
}

#elif OS_LINUX && (ARCH_ADDRSIZE == 64)



#else
# error selfimg not implemented for the targeted image format
#endif /* OS-switch */
