progmem.sh 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/bin/sh
  2. #
  3. # Multi-language support postbuild script
  4. # Description of proces:
  5. # 0. remove output files
  6. # 1. list symbol table of section '.text' from output elf file to text.sym (sorted by address)
  7. # 2. list symbol table of section '.$PROGMEM' from all output object files to $PROGMEM.sym
  8. # 3. filter only $PROGMEM symbols from text.sym and store it back to $PROGMEM.sym with absolute address
  9. # 4. calculate start and stop address of section '.$PROGMEM'
  10. # 5. extract string data from elf file to $PROGMEM.dat
  11. # 6. prepare string data for character check and conversion (output to $PROGMEM.chr)
  12. # 7. perform character check and conversion (output to $PROGMEM.var and $PROGMEM.txt)
  13. #
  14. # Input files:
  15. # Firmware.ino.elf
  16. # *.o (all object files)
  17. #
  18. # Output files:
  19. # text.sym
  20. # $PROGMEM.sym
  21. # $PROGMEM.lss
  22. # $PROGMEM.dat
  23. # $PROGMEM.chr
  24. # $PROGMEM.var
  25. # $PROGMEM.txt
  26. #
  27. # Program memory used
  28. PROGMEM=progmem$1
  29. if [ -z "$1" ]; then PROGMEM=progmem1; fi
  30. #
  31. # Output folder and elf file:
  32. OUTDIR="../../output"
  33. OUTELF="$OUTDIR/Firmware.ino.elf"
  34. #
  35. # AVR gcc tools used:
  36. OBJDUMP=C:/arduino-1.6.8/hardware/tools/avr/bin/avr-objdump.exe
  37. #READELF=C:/arduino-1.6.8/hardware/tools/avr/bin/avr-readelf.exe
  38. # (0)
  39. echo "step 0 - removing output files"
  40. #remove output files if exists
  41. if [ -e text.sym ]; then rm text.sym; fi
  42. if [ -e $PROGMEM.sym ]; then rm $PROGMEM.sym; fi
  43. if [ -e $PROGMEM.lss ]; then rm $PROGMEM.lss; fi
  44. if [ -e $PROGMEM.dat ]; then rm $PROGMEM.dat; fi
  45. if [ -e $PROGMEM.chr ]; then rm $PROGMEM.chr; fi
  46. if [ -e $PROGMEM.var ]; then rm $PROGMEM.var; fi
  47. if [ -e $PROGMEM.txt ]; then rm $PROGMEM.txt; fi
  48. # (1)
  49. echo "step 1 - listing symbol table of section '.text'"
  50. #list symbols from section '.text' into file text.sym (only address, size and name)
  51. $OBJDUMP -t -j ".text" $OUTELF | tail -n +5 | grep -E "^[0-9a-f]{8} [gl] O" | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> text.sym
  52. # (2)
  53. echo "step 2 - listing symbol table of section '.$PROGMEM'"
  54. #loop over all object files
  55. ls "$OUTDIR"/sketch/*.o | while read fn; do
  56. echo " processing $fn"
  57. #list symbols from section $PROGMEM (only address, size and name)
  58. $OBJDUMP -t -j ".$PROGMEM" $fn | tail -n +5 | cut -c1-9,28-36,37- | sed "/^$/d" | sort >> $PROGMEM.sym
  59. done 2>/dev/null
  60. # (3)
  61. echo "step 3 - filtering $PROGMEM symbols"
  62. #create list of $PROGMEM symbol names separated by '\|'
  63. progmem=$(cut -c19- $PROGMEM.sym)
  64. progmem=$(echo $progmem | sed "s/ /\\\|/g")
  65. #filter $PROGMEM symbols from section '.text' (result file will contain list sorted by absolute address)
  66. cat text.sym | grep $progmem > $PROGMEM.sym
  67. # (4)
  68. echo "step 4 - calculating start and stop address"
  69. #calculate start addres of section ".$PROGMEM"
  70. PROGMEM_BEG=$(head -n1 $PROGMEM.sym | while read offs size name; do echo "0x"$offs; done)
  71. #calculate stop addres of section ".$PROGMEM"
  72. PROGMEM_END=$(tail -n1 $PROGMEM.sym | while read offs size name; do printf "0x%x" $(("0x"$offs + "0x"$size)); done)
  73. echo " START address = "$PROGMEM_BEG
  74. echo " STOP address = "$PROGMEM_END
  75. # (5)
  76. echo "step 5 - extracting string data from elf"
  77. #dump $PROGMEM data in hex format, cut textual data (keep hex data only)
  78. $OBJDUMP -d -j ".text" -w -z --start-address=$PROGMEM_BEG --stop-address=$PROGMEM_END $OUTELF | cut -c1-57 > $PROGMEM.lss
  79. #convert $PROGMEM.lss to $PROGMEM.dat:
  80. # replace empty lines with '|' (variables separated by empty lines)
  81. # remove address from multiline variables (keep address at first variable line only)
  82. # remove '<' and '>:', remove whitespace at end of lines
  83. # remove line-endings, replace separator with '\n' (join hex data lines - each line will contain single variable)
  84. # filter progmem symbols
  85. cat $PROGMEM.lss | tail -n +7 | sed -E 's/^$/|/;s/^........:\t/ /;s/<//g;s/>:/ /g;s/[ \t]*$//' |\
  86. tr -d '\n' | sed "s/[|]/\n/g" | grep $progmem > $PROGMEM.dat
  87. # (6)
  88. echo "step 6 - preparing string data"
  89. #convert $PROGMEM.dat to $PROGMEM.chr (prepare string data for character check and conversion)
  90. # replace first space with tab
  91. # replace second space with tab and space
  92. # replace all remaining spaces with '\x'
  93. # replace all tabs with spaces
  94. cat $PROGMEM.dat | sed 's/ /\t/;s/ /\t /;s/ /\\x/g;s/\t/ /g' > $PROGMEM.chr
  95. # (7)
  96. #convert $PROGMEM.chr to $PROGMEM.var (convert data to text)
  97. cat $PROGMEM.chr | \
  98. sed 's/\\x22/\\\\\\x22/g;' | \
  99. sed 's/\\x1b/\\\\\\x1b/g;' | \
  100. sed 's/\\x01/\\\\\\x01/g;' | \
  101. sed 's/\\x00$/\\x0d/;s/^/printf "/;s/$/"/' | sh > $PROGMEM.var
  102. cat $PROGMEM.var | sed 's/\r/\n/g' |sed -E 's/^[0-9a-f]{8} [^ ]* //' >$PROGMEM.txt
  103. read