Mercurial > hg > dmlib
comparison tools/objlink.c @ 1679:7b0c76cd7686
Clean up and improve error handling.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 31 May 2018 13:18:44 +0300 |
parents | bddedc2e0ebb |
children | bd68c9adc7ca |
comparison
equal
deleted
inserted
replaced
1678:bddedc2e0ebb | 1679:7b0c76cd7686 |
---|---|
198 } | 198 } |
199 | 199 |
200 | 200 |
201 /* Memory block handling | 201 /* Memory block handling |
202 */ | 202 */ |
203 void reserveMemBlock(int startAddr, int endAddr, const char *blockName, int blockType) | 203 BOOL dmReserveMemBlock(int startAddr, int endAddr, const char *blockName, int blockType) |
204 { | 204 { |
205 if (startAddr > endAddr) | 205 if (startAddr > endAddr) |
206 { | 206 { |
207 dmErrorMsg("ERROR! Block '%s' has startAddr=$%.4x > endAddr=$%.4x!\n", | 207 dmErrorMsg("ERROR! Block '%s' has startAddr=$%.4x > endAddr=$%.4x!\n", |
208 blockName, startAddr, endAddr); | 208 blockName, startAddr, endAddr); |
209 exit(4); | 209 return FALSE; |
210 } | 210 } |
211 | 211 |
212 if (nmemBlocks < MAX_FILENAMES) | 212 if (nmemBlocks < MAX_FILENAMES) |
213 { | 213 { |
214 memBlocks[nmemBlocks].start = startAddr; | 214 memBlocks[nmemBlocks].start = startAddr; |
215 memBlocks[nmemBlocks].end = endAddr; | 215 memBlocks[nmemBlocks].end = endAddr; |
216 memBlocks[nmemBlocks].name = dm_strdup(blockName); | 216 memBlocks[nmemBlocks].name = dm_strdup(blockName); |
217 memBlocks[nmemBlocks].type = blockType; | 217 memBlocks[nmemBlocks].type = blockType; |
218 nmemBlocks++; | 218 nmemBlocks++; |
219 return TRUE; | |
219 } | 220 } |
220 else | 221 else |
221 { | 222 { |
222 dmErrorMsg("Maximum number of memBlock definitions (%d) exceeded!\n", | 223 dmErrorMsg("Maximum number of memBlock definitions (%d) exceeded!\n", |
223 MAX_FILENAMES); | 224 MAX_FILENAMES); |
224 exit(4); | 225 return FALSE; |
225 } | 226 } |
226 } | 227 } |
227 | 228 |
228 | 229 |
229 int compareMemBlock(const void *cva, const void *cvb) | 230 int dmCompareMemBlock(const void *cva, const void *cvb) |
230 { | 231 { |
231 const DMMemBlock *a = cva, *b = cvb; | 232 const DMMemBlock *a = cva, *b = cvb; |
232 return a->start - b->start; | 233 return a->start - b->start; |
233 } | 234 } |
234 | 235 |
235 | 236 |
236 BOOL dmParseSection(const char *arg, unsigned int *sectStart, unsigned int *sectEnd, char **sectName, BOOL canHasName) | 237 BOOL dmParseSection(const char *arg, unsigned int *sectStart, unsigned int *sectEnd, char **sectName, BOOL canHasName) |
237 { | 238 { |
238 char sectMode, *sep, *str, *namesep; | 239 char sectMode, *sep, *str, *namesep; |
239 unsigned int tmpi; | 240 unsigned int tmpi; |
241 BOOL res = FALSE; | |
240 | 242 |
241 // Define reserved section | 243 // Define reserved section |
242 // Create a copy of the argument | 244 // Create a copy of the argument |
243 if ((str = dm_strdup(arg)) == NULL) | 245 if ((str = dm_strdup(arg)) == NULL) |
244 { | 246 { |
245 dmErrorMsg("Could not allocate temporary string!\n"); | 247 dmErrorMsg("Could not allocate temporary string!\n"); |
246 exit(128); | 248 goto out; |
247 } | 249 } |
248 | 250 |
249 // Get start address | 251 // Get start address |
250 if ((sep = strchr(str, '-')) == NULL && | 252 if ((sep = strchr(str, '-')) == NULL && |
251 (sep = strchr(str, ':')) == NULL) | 253 (sep = strchr(str, ':')) == NULL) |
252 { | 254 { |
253 dmErrorMsg("Section definition '%s' invalid.\n", arg); | 255 dmErrorMsg("Section definition '%s' invalid.\n", arg); |
254 goto error; | 256 goto out; |
255 } | 257 } |
256 sectMode = *sep; | 258 sectMode = *sep; |
257 *sep = 0; | 259 *sep = 0; |
258 | 260 |
259 // Get value | 261 // Get value |
260 if (!dmGetIntVal(str, sectStart)) | 262 if (!dmGetIntVal(str, sectStart)) |
261 { | 263 { |
262 dmErrorMsg("Section start address '%s' in '%s' invalid.\n", str, arg); | 264 dmErrorMsg("Section start address '%s' in '%s' invalid.\n", str, arg); |
263 goto error; | 265 goto out; |
264 } | 266 } |
265 | 267 |
266 // Check for name | 268 // Check for name |
267 namesep = strchr(sep + 1, ','); | 269 namesep = strchr(sep + 1, ','); |
268 if (canHasName && namesep != NULL) | 270 if (canHasName && namesep != NULL) |
271 namesep++; | 273 namesep++; |
272 if (*namesep == 0) | 274 if (*namesep == 0) |
273 { | 275 { |
274 dmErrorMsg("Section definition '%s' name is empty. Either specify name or leave it out.\n", | 276 dmErrorMsg("Section definition '%s' name is empty. Either specify name or leave it out.\n", |
275 arg); | 277 arg); |
276 goto error; | 278 goto out; |
277 } | 279 } |
278 *sectName = dm_strdup(namesep); | 280 *sectName = dm_strdup(namesep); |
279 } | 281 } |
280 else | 282 else |
281 if (namesep != NULL) | 283 if (namesep != NULL) |
282 { | 284 { |
283 dmErrorMsg("Section definition does not allow a name, syntax error in '%s' at '%s'.\n", | 285 dmErrorMsg("Section definition does not allow a name, syntax error in '%s' at '%s'.\n", |
284 arg, namesep); | 286 arg, namesep); |
285 goto error; | 287 goto out; |
286 } | 288 } |
287 | 289 |
288 // Get end address or length | 290 // Get end address or length |
289 if (!dmGetIntVal(sep + 1, &tmpi)) | 291 if (!dmGetIntVal(sep + 1, &tmpi)) |
290 { | 292 { |
291 dmErrorMsg("Section %s '%s' in '%s' invalid.\n", | 293 dmErrorMsg("Section %s '%s' in '%s' invalid.\n", |
292 sectMode == '-' ? "end address" : "length", | 294 sectMode == '-' ? "end address" : "length", |
293 sep + 1, arg); | 295 sep + 1, arg); |
294 goto error; | 296 goto out; |
295 } | 297 } |
296 | 298 |
297 if (sectMode == ':') | 299 if (sectMode == ':') |
298 { | 300 { |
299 *sectEnd = *sectStart + tmpi - 1; | 301 *sectEnd = *sectStart + tmpi - 1; |
302 { | 304 { |
303 if (tmpi < *sectStart) | 305 if (tmpi < *sectStart) |
304 { | 306 { |
305 dmErrorMsg("Section start address > end address in '%s'.\n", | 307 dmErrorMsg("Section start address > end address in '%s'.\n", |
306 arg); | 308 arg); |
307 goto error; | 309 goto out; |
308 } | 310 } |
309 *sectEnd = tmpi; | 311 *sectEnd = tmpi; |
310 } | 312 } |
311 | 313 |
314 res = TRUE; | |
315 | |
316 out: | |
312 dmFree(str); | 317 dmFree(str); |
313 return TRUE; | 318 return res; |
314 | |
315 error: | |
316 dmFree(str); | |
317 return FALSE; | |
318 } | 319 } |
319 | 320 |
320 | 321 |
321 BOOL dmParseInputFile(char *arg, const int type1, const int type2, const char *desc, BOOL requireAddr) | 322 BOOL dmParseInputFile(char *arg, const int type1, const int type2, const char *desc, BOOL requireAddr) |
322 { | 323 { |
460 // Allocate memory block | 461 // Allocate memory block |
461 sectLen = sectEnd - sectStart + 1; | 462 sectLen = sectEnd - sectStart + 1; |
462 dmMsg(1, "Reserve $%.4x - $%.4x ($%x, %d bytes) as '%s'\n", | 463 dmMsg(1, "Reserve $%.4x - $%.4x ($%x, %d bytes) as '%s'\n", |
463 sectStart, sectEnd, sectLen, sectLen, sectName); | 464 sectStart, sectEnd, sectLen, sectLen, sectName); |
464 | 465 |
465 reserveMemBlock(sectStart, sectEnd, sectName, MTYPE_RES); | 466 if (!dmReserveMemBlock(sectStart, sectEnd, sectName, MTYPE_RES)) |
467 return FALSE; | |
466 } | 468 } |
467 break; | 469 break; |
468 | 470 |
469 case 13: | 471 case 13: |
470 { | 472 { |
567 } | 569 } |
568 | 570 |
569 dmPrint(1, " .. OK\n"); | 571 dmPrint(1, " .. OK\n"); |
570 | 572 |
571 // Add to list of blocks | 573 // Add to list of blocks |
572 reserveMemBlock(loadAddr, endAddr, filename, MTYPE_RES); | 574 if (!dmReserveMemBlock(loadAddr, endAddr, filename, MTYPE_RES)) |
575 res = DMERR_MALLOC; | |
573 | 576 |
574 out: | 577 out: |
575 if (fh != NULL) | 578 if (fh != NULL) |
576 fclose(fh); | 579 fclose(fh); |
577 | 580 |
623 } | 626 } |
624 | 627 |
625 dmPrint(1, " .. OK\n"); | 628 dmPrint(1, " .. OK\n"); |
626 | 629 |
627 // Add info to list | 630 // Add info to list |
628 reserveMemBlock(destAddr, endAddr, filename, MTYPE_RES); | 631 if (!dmReserveMemBlock(destAddr, endAddr, filename, MTYPE_RES)) |
632 res = DMERR_MALLOC; | |
629 | 633 |
630 out: | 634 out: |
631 if (fh != NULL) | 635 if (fh != NULL) |
632 fclose(fh); | 636 fclose(fh); |
633 | 637 |
782 dmVerbosity = 1; | 786 dmVerbosity = 1; |
783 | 787 |
784 // Parse arguments | 788 // Parse arguments |
785 if (!dmArgsProcess(argc, argv, optList, optListN, | 789 if (!dmArgsProcess(argc, argv, optList, optListN, |
786 argHandleOpt, NULL, OPTH_BAILOUT)) | 790 argHandleOpt, NULL, OPTH_BAILOUT)) |
787 exit(1); | 791 goto out; |
788 | 792 |
789 if (nsrcFiles < 1) | 793 if (nsrcFiles < 1) |
790 { | 794 { |
791 dmErrorMsg("Nothing to do. (try --help)\n"); | 795 dmErrorMsg("Nothing to do. (try --help)\n"); |
792 exit(0); | 796 goto out; |
793 } | 797 } |
794 | 798 |
795 // Allocate memory | 799 // Allocate memory |
796 memModel = &memoryModels[optMemModel]; | 800 memModel = &memoryModels[optMemModel]; |
797 dmMsg(1, "Using memory model #%d '%s', %d bytes.\n", | 801 dmMsg(1, "Using memory model #%d '%s', %d bytes.\n", |
798 optMemModel, memModel->name, memModel->size); | 802 optMemModel, memModel->name, memModel->size); |
799 | 803 |
800 memory = (Uint8 *) dmMalloc(memModel->size + 32); | 804 if ((memory = (Uint8 *) dmMalloc(memModel->size + 32)) == NULL) |
801 if (memory == NULL) | 805 { |
802 { | 806 dmErrorMsg("Could not allocate memory for memory model!\n"); |
803 dmErrorMsg("Could not allocate memory.\n"); | 807 goto out; |
804 exit(2); | |
805 } | 808 } |
806 | 809 |
807 // Initialize memory | 810 // Initialize memory |
808 dmMsg(1, "Initializing memory with "); | 811 dmMsg(1, "Initializing memory with "); |
809 | 812 |
851 | 854 |
852 // Add memory model blocks | 855 // Add memory model blocks |
853 dmMsg(1, "Applying memory model restrictions...\n"); | 856 dmMsg(1, "Applying memory model restrictions...\n"); |
854 for (int i = 0; i < memModel->nmemBlocks; i++) | 857 for (int i = 0; i < memModel->nmemBlocks; i++) |
855 { | 858 { |
856 reserveMemBlock( | 859 if (!dmReserveMemBlock( |
857 memModel->memBlocks[i].start, | 860 memModel->memBlocks[i].start, |
858 memModel->memBlocks[i].end, | 861 memModel->memBlocks[i].end, |
859 memModel->memBlocks[i].name, | 862 memModel->memBlocks[i].name, |
860 memModel->memBlocks[i].type); | 863 memModel->memBlocks[i].type)) |
864 goto out; | |
861 } | 865 } |
862 | 866 |
863 // Sort the blocks | 867 // Sort the blocks |
864 qsort(memBlocks, nmemBlocks, sizeof(DMMemBlock), compareMemBlock); | 868 qsort(memBlocks, nmemBlocks, sizeof(DMMemBlock), dmCompareMemBlock); |
865 | 869 |
866 // Check for overlapping conflicts | 870 // Check for overlapping conflicts |
867 hasOverlaps = FALSE; | 871 hasOverlaps = FALSE; |
868 for (int i = 0; i < nmemBlocks; i++) | 872 for (int i = 0; i < nmemBlocks; i++) |
869 for (int j = 0; j < nmemBlocks; j++) | 873 for (int j = 0; j < nmemBlocks; j++) |
884 } | 888 } |
885 | 889 |
886 if (!optAllowOverlap && hasOverlaps) | 890 if (!optAllowOverlap && hasOverlaps) |
887 { | 891 { |
888 dmErrorMsg("Error occured, overlaps not allowed.\n"); | 892 dmErrorMsg("Error occured, overlaps not allowed.\n"); |
889 exit(5); | 893 goto out; |
890 } | 894 } |
891 | 895 |
892 // Find out start and end-addresses | 896 // Find out start and end-addresses |
893 startAddr = memModel->size; | 897 startAddr = memModel->size; |
894 totalSize = endAddr = 0; | 898 totalSize = endAddr = 0; |
907 } | 911 } |
908 } | 912 } |
909 | 913 |
910 if (startAddr >= memModel->size || endAddr < startAddr) | 914 if (startAddr >= memModel->size || endAddr < startAddr) |
911 { | 915 { |
912 dmErrorMsg("Invalid saveblock addresses (start=$%.4x, end=$%.4x)!\n", startAddr, endAddr); | 916 dmErrorMsg("Invalid saveblock addresses (start=$%.4x, end=$%.4x)!\n", |
913 exit(8); | 917 startAddr, endAddr); |
918 goto out; | |
914 } | 919 } |
915 | 920 |
916 // Output linkfile | 921 // Output linkfile |
917 if (optLinkFileName) | 922 if (optLinkFileName) |
918 { | 923 { |
920 if ((dfile = fopen(optLinkFileName, "wb")) == NULL) | 925 if ((dfile = fopen(optLinkFileName, "wb")) == NULL) |
921 { | 926 { |
922 int err = dmGetErrno(); | 927 int err = dmGetErrno(); |
923 dmErrorMsg("Error creating file '%s' #%d: %s.\n", | 928 dmErrorMsg("Error creating file '%s' #%d: %s.\n", |
924 optLinkFileName, err, dmErrorStr(err)); | 929 optLinkFileName, err, dmErrorStr(err)); |
925 exit(1); | 930 goto out; |
926 } | 931 } |
927 | 932 |
928 switch (optLinkFileFormat) | 933 switch (optLinkFileFormat) |
929 { | 934 { |
930 case FMT_GENERIC: | 935 case FMT_GENERIC: |
971 else if ((dfile = fopen(optDestName, "wb")) == NULL) | 976 else if ((dfile = fopen(optDestName, "wb")) == NULL) |
972 { | 977 { |
973 int err = dmGetErrno(); | 978 int err = dmGetErrno(); |
974 dmErrorMsg("Error creating output file '%s' #%d: %s.\n", | 979 dmErrorMsg("Error creating output file '%s' #%d: %s.\n", |
975 optDestName, err, dmErrorStr(err)); | 980 optDestName, err, dmErrorStr(err)); |
976 exit(1); | 981 goto out; |
977 } | 982 } |
978 else | 983 else |
979 dmPrint(1, "to '%s'\n", optDestName); | 984 dmPrint(1, "to '%s'\n", optDestName); |
980 | 985 |
981 // Save loading address | 986 // Save loading address |
999 if (fwrite(&memory[startAddr], dataSize, 1, dfile) < 1) | 1004 if (fwrite(&memory[startAddr], dataSize, 1, dfile) < 1) |
1000 { | 1005 { |
1001 int err = dmGetErrno(); | 1006 int err = dmGetErrno(); |
1002 dmErrorMsg("Error writing to file #%d: %s.\n", | 1007 dmErrorMsg("Error writing to file #%d: %s.\n", |
1003 err, dmErrorStr(err)); | 1008 err, dmErrorStr(err)); |
1004 } | 1009 goto out; |
1005 | 1010 } |
1006 fclose(dfile); | 1011 |
1007 | 1012 // Describe the memory layout |
1008 // Describe | |
1009 if (optDescribe) | 1013 if (optDescribe) |
1010 dmDescribeMemory(stdout); | 1014 dmDescribeMemory(dfile != stdout ? stdout : stderr); |
1015 | |
1016 out: | |
1017 if (dfile != NULL && dfile != stdout) | |
1018 fclose(dfile); | |
1011 | 1019 |
1012 return 0; | 1020 return 0; |
1013 } | 1021 } |