implementation module WriteMapFile; import State; import ExtFile; import ExtInt; from StdOrdList import sortBy; :: MapRecord = { offset :: !Int , symbol_name :: !String , file_name :: !String }; :: ColumnWidths = { symbol_name_column :: !Int , file_name_column :: !Int }; DefaultColumnWidths :: ColumnWidths; DefaultColumnWidths = { ColumnWidths | symbol_name_column = 0 , file_name_column = 0 }; //import DebugUtilities; generate_map_file :: !*State !*Files -> (!*State,!*Files); generate_map_file state=:{application_name,xcoff_a} files // create map file #! map_file_name = fst (ExtractPathFileAndExtension application_name) +++ ".map"; #! (ok,map_file,files) = fopen map_file_name FWriteText files; | not ok # msg = "could not open map file '" +++ map_file_name +++ "'"; = (AddMessage (LinkerError msg) state,files); #! map_file = fwrites ("Map file for " +++ application_name +++ "\n\n") map_file; // generate map #! column_widths = { ColumnWidths | symbol_name_column = s_symbol_name_column , file_name_column = s_file_name_column }; #! (names_table,state) = acc_namestable (\names_table -> (names_table,{})) state; #! (map_records,column_widths,names_table,state) = generate_map_records [] 0 column_widths names_table state; #! map_records = sortBy (\{offset=offset1} {offset=offset2} -> offset1 < offset2) map_records; #! state = { state & namestable = names_table }; // write map to disk; calculate max widths of columns #! tab_size = 4; #! column_widths = { ColumnWidths | symbol_name_column = (roundup_to_multiple column_widths.symbol_name_column tab_size) , file_name_column = (roundup_to_multiple column_widths.file_name_column tab_size) }; // write header #! map_file = format "Offset:" max_offset_column_size map_file; #! map_file = format symbol_name_column column_widths.symbol_name_column map_file; #! map_file = format file_name_column column_widths.file_name_column map_file; #! map_file = fwritec '\n' map_file; #! map_file = foldl (f column_widths) map_file map_records; // close map file #! (_,files) = fclose map_file files; = (state,files); where { // constants max_offset_column_size = 14; // 2nd column symbol_name_column = "Symbol name:"; s_symbol_name_column = size symbol_name_column; // 3th column file_name_column = "File:"; s_file_name_column = size file_name_column; // write table f column_witdhs=:{symbol_name_column,file_name_column} map_file {offset,symbol_name,file_name} // write offset from base #! map_file = format (hex_int offset) max_offset_column_size map_file; // write symbol name #! map_file = format symbol_name symbol_name_column map_file; // write name of defining file #! map_file = fwrites file_name map_file; #! map_file = fwritec '\n' map_file; = map_file; where { } format s max_s map_file #! map_file = fwrites s map_file; #! map_file = fwrite_tabs (max_s - size s) map_file; = map_file; where { fwrite_tabs n map_file | n == 0 = map_file; = fwrite_tabs (dec n) (fwritec ' ' map_file); } /* :: ColumnWidths = { symbol_name_column :: !Int , file_name_column :: !Int }; */ // generate_map_records :: ![!*MapRecord] *(!*NamesTable -> (![!*MapRecord],!*NamesTable)); generate_map_records map_records i column_widths names_table state | i == SYMBOL_TABLE_SIZE = (map_records,column_widths,names_table,state); #! (names_table_element,names_table) = names_table![i]; #! (column_widths,map_records,state) = generate_more_map_records column_widths map_records names_table_element state; = generate_map_records map_records (inc i) column_widths names_table state; where { generate_more_map_records column_widths map_records EmptyNamesTableElement state = (column_widths,map_records,state); generate_more_map_records column_widths=:{symbol_name_column,file_name_column} map_records (NamesTableElement symbol_name symbol_n file_n names_table_elements) state | file_n < 0 = generate_more_map_records column_widths map_records names_table_elements state; #! (first_symbol_n,state) = selacc_marked_offset_a file_n state; #! (symbol_marked,state) = selacc_marked_bool_a (first_symbol_n + symbol_n) state; | symbol_marked #! (offset,state) = address_of_label3 file_n symbol_n state; #! (file_name,state) = select_file_name file_n state; #! (_,file_name) = ExtractPathAndFile file_name; #! map_record = { MapRecord | offset = offset , symbol_name = symbol_name , file_name = file_name }; # max_symbol_name_column = max (size symbol_name) symbol_name_column; # max_file_name_column = max (size file_name) file_name_column; #! column_widths = if ((max_symbol_name_column > symbol_name_column) || (max_file_name_column > file_name_column)) {symbol_name_column = max_symbol_name_column,file_name_column=max_file_name_column} column_widths; = generate_more_map_records column_widths [map_record:map_records] names_table_elements state; = generate_more_map_records column_widths map_records names_table_elements state; where { max_symbol_name_column = max } } } /* acc_namestable :: (*NamesTable -> (.x,*NamesTable)) !*State -> (!.x,!*State); sort find_address_of_label :: !String !State -> !(!Bool,!Int,!State); MergeNamesTables :: !NamesTable !NamesTable -> !NamesTable; MergeNamesTables names_table1 names_table2 = { (merge names_table_element1 names_table_element2) \\ names_table_element1 <-: names_table1 & names_table_element2 <-: names_table2 }; where { merge :: !NamesTableElement !NamesTableElement -> !NamesTableElement; merge names_table_element1 EmptyNamesTableElement = names_table_element1; merge names_table_element1 (NamesTableElement symbol_name symbol_n file_n more_names_table_elements) | name_in_names_table_list names_table_element1 = abort ("MergeNamesTables: double defined symbols" +++ symbol_name); = merge (NamesTableElement symbol_name symbol_n file_n names_table_element1) more_names_table_elements; where { name_in_names_table_list EmptyNamesTableElement = False; name_in_names_table_list (NamesTableElement string _ _ names_table_list) | string == symbol_name = True; = name_in_names_table_list names_table_list } } */ address_of_label3 :: !Int !Int !State -> (!Int,!State); address_of_label3 file_n symbol_n state = address_of_label2 file_n symbol_n state;