vita-import-parse.c (9438B)
1 #include <string.h> 2 #include <stdlib.h> 3 #include "vita-import.h" 4 #include "yamltree.h" 5 #include "yamltreeutil.h" 6 #include "sha256.h" 7 8 int process_import_functions(yaml_node *parent, yaml_node *child, vita_imports_module_t *library) { 9 if (!is_scalar(parent)) { 10 fprintf(stderr, "error: line: %zd, column: %zd, expecting function to be scalar, got '%s'.\n" 11 , parent->position.line 12 , parent->position.column 13 , node_type_str(parent)); 14 15 return -1; 16 } 17 18 yaml_scalar *key = &parent->data.scalar; 19 20 // create an export symbol for this function 21 vita_imports_stub_t *symbol = vita_imports_stub_new(key->value,0); 22 23 if (!is_scalar(child)) { 24 fprintf(stderr, "error: line: %zd, column: %zd, expecting function value to be scalar, got '%s'.\n" 25 , child->position.line 26 , child->position.column 27 , node_type_str(child)); 28 29 return -1; 30 } 31 32 if (process_32bit_integer(child, &symbol->NID) < 0) { 33 fprintf(stderr, "error: line: %zd, column: %zd, could not convert function nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value); 34 return -1; 35 } 36 // append to list 37 library->functions = realloc(library->functions, (library->n_functions+1)*sizeof(vita_imports_stub_t*)); 38 library->functions[library->n_functions++] = symbol; 39 40 return 0; 41 } 42 43 int process_import_variables(yaml_node *parent, yaml_node *child, vita_imports_module_t *library) { 44 if (!is_scalar(parent)) { 45 fprintf(stderr, "error: line: %zd, column: %zd, expecting variable to be scalar, got '%s'.\n" 46 , parent->position.line 47 , parent->position.column 48 , node_type_str(parent)); 49 50 return -1; 51 } 52 53 yaml_scalar *key = &parent->data.scalar; 54 55 // create an export symbol for this variable 56 vita_imports_stub_t *symbol = vita_imports_stub_new(key->value,0); 57 58 if (!is_scalar(child)) { 59 fprintf(stderr, "error: line: %zd, column: %zd, expecting variable value to be scalar, got '%s'.\n" 60 , child->position.line 61 , child->position.column 62 , node_type_str(child)); 63 64 return -1; 65 } 66 67 if (process_32bit_integer(child, &symbol->NID) < 0) { 68 fprintf(stderr, "error: line: %zd, column: %zd, could not convert variable nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value); 69 return -1; 70 } 71 // append to list 72 library->variables = realloc(library->variables, (library->n_variables+1)*sizeof(vita_imports_stub_t*)); 73 library->variables[library->n_variables++] = symbol; 74 75 return 0; 76 } 77 78 int process_library(yaml_node *parent, yaml_node *child, vita_imports_module_t *library) { 79 if (!is_scalar(parent)) { 80 fprintf(stderr, "error: line: %zd, column: %zd, expecting library key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent)); 81 return -1; 82 } 83 84 yaml_scalar *key = &parent->data.scalar; 85 86 if (strcmp(key->value, "kernel") == 0) { 87 if (!is_scalar(child)) { 88 fprintf(stderr, "error: line: %zd, column: %zd, expecting library syscall flag to be scalar, got '%s'.\n", child->position.line, child->position.column, node_type_str(child)); 89 return -1; 90 } 91 92 if (process_bool(child, &library->is_kernel) < 0) { 93 fprintf(stderr, "error: line: %zd, column: %zd, could not convert library flag to boolean, got '%s'. expected 'true' or 'false'.\n", child->position.line, child->position.column, child->data.scalar.value); 94 return -1; 95 } 96 } 97 else if (strcmp(key->value, "functions") == 0) { 98 if (yaml_iterate_mapping(child, (mapping_functor)process_import_functions, library) < 0) 99 return -1; 100 } 101 else if (strcmp(key->value, "variables") == 0) { 102 if (yaml_iterate_mapping(child, (mapping_functor)process_import_variables, library) < 0) 103 return -1; 104 } 105 else if (strcmp(key->value, "nid") == 0) { 106 if (!is_scalar(child)) { 107 fprintf(stderr, "error: line: %zd, column: %zd, expecting library nid to be scalar, got '%s'.\n", child->position.line, child->position.column, node_type_str(child)); 108 return -1; 109 } 110 111 if (process_32bit_integer(child, &library->NID) < 0) { 112 fprintf(stderr, "error: line: %zd, column: %zd, could not convert library nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value); 113 return -1; 114 } 115 } 116 else { 117 fprintf(stderr, "error: line: %zd, column: %zd, unrecognised library key '%s'.\n", child->position.line, child->position.column, key->value); 118 return -1; 119 } 120 121 return 0; 122 } 123 124 int process_libraries(yaml_node *parent, yaml_node *child, vita_imports_lib_t *import) { 125 if (!is_scalar(parent)) { 126 fprintf(stderr, "error: line: %zd, column: %zd, expecting library key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent)); 127 return -1; 128 } 129 130 yaml_scalar *key = &parent->data.scalar; 131 132 vita_imports_module_t *library = vita_imports_module_new("",false,0,0,0); 133 134 // default values 135 library->name = strdup(key->value); 136 137 if (yaml_iterate_mapping(child, (mapping_functor)process_library, library) < 0) 138 return -1; 139 140 import->modules = realloc(import->modules, (import->n_modules+1)*sizeof(vita_imports_module_t*)); 141 import->modules[import->n_modules++] = library; 142 143 return 0; 144 } 145 146 int process_import(yaml_node *parent, yaml_node *child, vita_imports_lib_t *import) { 147 if (!is_scalar(parent)) { 148 fprintf(stderr, "error: line: %zd, column: %zd, expecting module key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent)); 149 return -1; 150 } 151 152 yaml_scalar *key = &parent->data.scalar; 153 154 if (strcmp(key->value, "nid") == 0) { 155 if (!is_scalar(child)) { 156 fprintf(stderr, "error: line: %zd, column: %zd, expecting module nid to be scalar, got '%s'.\n", child->position.line, child->position.column, node_type_str(child)); 157 return -1; 158 } 159 160 if (process_32bit_integer(child, &import->NID) < 0) { 161 fprintf(stderr, "error: line: %zd, column: %zd, could not convert module nid '%s' to 32 bit integer.\n", child->position.line, child->position.column, child->data.scalar.value); 162 return -1; 163 } 164 } 165 else if (strcmp(key->value, "libraries") == 0) { 166 167 if (yaml_iterate_mapping(child, (mapping_functor)process_libraries, import) < 0) 168 return -1; 169 170 } 171 else { 172 fprintf(stderr, "error: line: %zd, column: %zd, unrecognised module key '%s'.\n", child->position.line, child->position.column, key->value); 173 return -1; 174 } 175 176 return 0; 177 } 178 179 int process_import_list(yaml_node *parent, yaml_node *child, vita_imports_t *imports) { 180 if (!is_scalar(parent)) { 181 fprintf(stderr, "error: line: %zd, column: %zd, expecting modules key to be scalar, got '%s'.\n", parent->position.line, parent->position.column, node_type_str(parent)); 182 return -1; 183 } 184 185 yaml_scalar *key = &parent->data.scalar; 186 187 vita_imports_lib_t *import = vita_imports_lib_new(key->value,0,0); 188 189 if (yaml_iterate_mapping(child, (mapping_functor)process_import, import) < 0) 190 return -1; 191 192 imports->libs = realloc(imports->libs, (imports->n_libs+1)*sizeof(vita_imports_lib_t*)); 193 imports->libs[imports->n_libs++] = import; 194 return 0; 195 } 196 197 vita_imports_t *read_vita_imports(yaml_document *doc) { 198 if (!is_mapping(doc)) { 199 fprintf(stderr, "error: line: %zd, column: %zd, expecting root node to be a mapping, got '%s'.\n", doc->position.line, doc->position.column, node_type_str(doc)); 200 return NULL; 201 } 202 203 yaml_mapping *root = &doc->data.mapping; 204 205 // check we only have one entry 206 if (root->count < 1) { 207 fprintf(stderr, "error: line: %zd, column: %zd, expecting at least one entry within root mapping, got %zd.\n", doc->position.line, doc->position.column, root->count); 208 return NULL; 209 } 210 211 vita_imports_t *imports = vita_imports_new(0); 212 213 for(int n = 0; n < root->count; n++){ 214 // check lhs is a scalar 215 if (is_scalar(root->pairs[n]->lhs)) { 216 const char *root_value = root->pairs[n]->lhs->data.scalar.value; 217 if (strcmp(root_value, "firmware") == 0) { 218 if (!is_scalar(root->pairs[n]->rhs)) 219 return NULL; 220 const char *firm = root->pairs[n]->rhs->data.scalar.value; 221 // skip default firmware 222 if (strcmp(firm, "3.60") == 0) 223 continue; 224 imports->firmware = strdup(firm); 225 int i = 0; 226 int j = 0; 227 imports->postfix[j++] = '_'; 228 while (firm[i]) { 229 const char v = firm[i++]; 230 if (v == '.') 231 continue; 232 imports->postfix[j++] = v; 233 } 234 } 235 else if (strcmp(root_value, "modules") == 0) { 236 if (yaml_iterate_mapping(root->pairs[n]->rhs, (mapping_functor)process_import_list, imports) < 0) 237 return NULL; 238 } 239 else { 240 fprintf(stderr, "warning: line: %zd, column: %zd, unknow tag '%s'.\n", root->pairs[n]->lhs->position.line, root->pairs[n]->lhs->position.column, root->pairs[n]->lhs->data.scalar.value); 241 } 242 } 243 } 244 245 return imports; 246 247 } 248 249 vita_imports_t *vita_imports_load(const char *filename, int verbose) 250 { 251 FILE *fp = fopen(filename, "r"); 252 if (fp == NULL) { 253 fprintf(stderr, "Error: could not open %s\n", filename); 254 return NULL; 255 } 256 vita_imports_t *imports = vita_imports_loads(fp, verbose); 257 258 fclose(fp); 259 260 return imports; 261 } 262 263 vita_imports_t *vita_imports_loads(FILE *text, int verbose){ 264 uint32_t nid = 0; 265 yaml_error error = {0}; 266 267 yaml_tree *tree = parse_yaml_stream(text, &error); 268 269 if (!tree) 270 { 271 fprintf(stderr, "error: %s\n", error.problem); 272 free(error.problem); 273 return NULL; 274 } 275 276 if (tree->count != 1) 277 { 278 fprintf(stderr, "error: expecting a single yaml document, got: %zd\n", tree->count); 279 // TODO: cleanup tree 280 return NULL; 281 } 282 283 return read_vita_imports(tree->docs[0]); 284 }