@@ -37,6 +37,7 @@ use crate::{
37
37
} ,
38
38
util:: {
39
39
asm:: write_asm,
40
+ bin2c:: bin2c,
40
41
comment:: MWComment ,
41
42
config:: {
42
43
apply_splits_file, apply_symbols_file, is_auto_symbol, write_splits_file,
@@ -252,6 +253,22 @@ pub struct ModuleConfig {
252
253
/// Overrides links to other modules.
253
254
#[ serde( skip_serializing_if = "is_default" ) ]
254
255
pub links : Option < Vec < String > > ,
256
+ #[ serde( default , skip_serializing_if = "Vec::is_empty" ) ]
257
+ pub extract : Vec < ExtractConfig > ,
258
+ }
259
+
260
+ #[ derive( Serialize , Deserialize , Debug , Clone , PartialEq ) ]
261
+ pub struct ExtractConfig {
262
+ /// The name of the symbol to extract.
263
+ pub symbol : String ,
264
+ /// If specified, the symbol's data will be extracted to the given file.
265
+ /// Path is relative to `out_dir/bin`.
266
+ #[ serde( with = "path_slash_serde_option" , default , skip_serializing_if = "Option::is_none" ) ]
267
+ pub binary : Option < PathBuf > ,
268
+ /// If specified, the symbol's data will be extracted to the given file as a C array.
269
+ /// Path is relative to `out_dir/include`.
270
+ #[ serde( with = "path_slash_serde_option" , default , skip_serializing_if = "Option::is_none" ) ]
271
+ pub header : Option < PathBuf > ,
255
272
}
256
273
257
274
impl ModuleConfig {
@@ -776,6 +793,7 @@ fn load_analyze_dol(config: &ProjectConfig) -> Result<AnalyzeResult> {
776
793
fn split_write_obj (
777
794
module : & mut ModuleInfo ,
778
795
config : & ProjectConfig ,
796
+ base_dir : & Path ,
779
797
out_dir : & Path ,
780
798
no_update : bool ,
781
799
) -> Result < OutputModule > {
@@ -856,6 +874,37 @@ fn split_write_obj(
856
874
write_if_changed ( & out_path, & out_obj) ?;
857
875
}
858
876
877
+ // Write extracted files
878
+ for extract in & module. config . extract {
879
+ let ( _, symbol) = module
880
+ . obj
881
+ . symbols
882
+ . by_name ( & extract. symbol ) ?
883
+ . with_context ( || format ! ( "Failed to locate symbol '{}'" , extract. symbol) ) ?;
884
+ let section_index = symbol
885
+ . section
886
+ . with_context ( || format ! ( "Symbol '{}' has no section" , extract. symbol) ) ?;
887
+ let section = & module. obj . sections [ section_index] ;
888
+ let data = section. symbol_data ( symbol) ?;
889
+
890
+ if let Some ( binary) = & extract. binary {
891
+ let out_path = base_dir. join ( "bin" ) . join ( binary) ;
892
+ if let Some ( parent) = out_path. parent ( ) {
893
+ DirBuilder :: new ( ) . recursive ( true ) . create ( parent) ?;
894
+ }
895
+ write_if_changed ( & out_path, data) ?;
896
+ }
897
+
898
+ if let Some ( header) = & extract. header {
899
+ let header_string = bin2c ( symbol, section, data) ;
900
+ let out_path = base_dir. join ( "include" ) . join ( header) ;
901
+ if let Some ( parent) = out_path. parent ( ) {
902
+ DirBuilder :: new ( ) . recursive ( true ) . create ( parent) ?;
903
+ }
904
+ write_if_changed ( & out_path, header_string. as_bytes ( ) ) ?;
905
+ }
906
+ }
907
+
859
908
// Generate ldscript.lcf
860
909
let ldscript_template = if let Some ( template) = & module. config . ldscript_template {
861
910
Some ( fs:: read_to_string ( template) . with_context ( || {
@@ -894,7 +943,8 @@ fn write_if_changed(path: &Path, contents: &[u8]) -> Result<()> {
894
943
return Ok ( ( ) ) ;
895
944
}
896
945
}
897
- fs:: write ( path, contents) ?;
946
+ fs:: write ( path, contents)
947
+ . with_context ( || format ! ( "Failed to write file '{}'" , path. display( ) ) ) ?;
898
948
Ok ( ( ) )
899
949
}
900
950
@@ -1134,15 +1184,14 @@ fn split(args: SplitArgs) -> Result<()> {
1134
1184
let _span =
1135
1185
info_span ! ( "module" , name = %config. base. name( ) , id = dol. obj. module_id) . entered ( ) ;
1136
1186
dol_result = Some (
1137
- split_write_obj ( & mut dol, & config, & args. out_dir , args. no_update ) . with_context (
1138
- || {
1187
+ split_write_obj ( & mut dol, & config, & args. out_dir , & args. out_dir , args . no_update )
1188
+ . with_context ( || {
1139
1189
format ! (
1140
1190
"While processing object '{}' (module ID {})" ,
1141
1191
config. base. file_name( ) ,
1142
1192
dol. obj. module_id
1143
1193
)
1144
- } ,
1145
- ) ,
1194
+ } ) ,
1146
1195
) ;
1147
1196
} ) ;
1148
1197
// Modules
@@ -1155,7 +1204,7 @@ fn split(args: SplitArgs) -> Result<()> {
1155
1204
info_span ! ( "module" , name = %module. config. name( ) , id = module. obj. module_id)
1156
1205
. entered ( ) ;
1157
1206
let out_dir = args. out_dir . join ( module. config . name ( ) . as_ref ( ) ) ;
1158
- split_write_obj ( module, & config, & out_dir, args. no_update ) . with_context (
1207
+ split_write_obj ( module, & config, & args . out_dir , & out_dir, args. no_update ) . with_context (
1159
1208
|| {
1160
1209
format ! (
1161
1210
"While processing object '{}' (module {} ID {})" ,
@@ -1697,6 +1746,7 @@ fn config(args: ConfigArgs) -> Result<()> {
1697
1746
force_active : vec ! [ ] ,
1698
1747
ldscript_template : None ,
1699
1748
links : None ,
1749
+ extract : vec ! [ ] ,
1700
1750
} ,
1701
1751
selfile : None ,
1702
1752
selfile_hash : None ,
@@ -1733,6 +1783,7 @@ fn config(args: ConfigArgs) -> Result<()> {
1733
1783
force_active : vec ! [ ] ,
1734
1784
ldscript_template : None ,
1735
1785
links : None ,
1786
+ extract : vec ! [ ] ,
1736
1787
} ) ) ;
1737
1788
}
1738
1789
Some ( ext) if ext. eq_ignore_ascii_case ( OsStr :: new ( "sel" ) ) => {
@@ -1750,6 +1801,7 @@ fn config(args: ConfigArgs) -> Result<()> {
1750
1801
force_active : vec ! [ ] ,
1751
1802
ldscript_template : None ,
1752
1803
links : None ,
1804
+ extract : vec ! [ ] ,
1753
1805
} ) ;
1754
1806
}
1755
1807
_ => bail ! ( "Unknown file extension: '{}'" , path. display( ) ) ,
0 commit comments