From b6d1d9068c41a0dec960f723b66555c0d96e1535 Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 29 Nov 2023 16:28:23 -0800 Subject: readelf: Fix the section flags handling. The array of section flags was missing the G flag, so any flags after it were displayed incorrectly. And, of course, the G flag was not displayed at all. Added a new elf file with a section that include the T and C flags and updated readelf.test to run this test. This test fails on the old code and passes with the fix. --- tests/files/elf/ndk-elf-note-shflags | Bin 0 -> 4308 bytes tests/readelf.test | 36 +++++++++++++++++++++++++++++++++++ toys/other/readelf.c | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100755 tests/files/elf/ndk-elf-note-shflags diff --git a/tests/files/elf/ndk-elf-note-shflags b/tests/files/elf/ndk-elf-note-shflags new file mode 100755 index 00000000..684a78bf Binary files /dev/null and b/tests/files/elf/ndk-elf-note-shflags differ diff --git a/tests/readelf.test b/tests/readelf.test index 1e85e45e..2f0a4712 100755 --- a/tests/readelf.test +++ b/tests/readelf.test @@ -70,6 +70,42 @@ Section Headers: [31] .strtab STRTAB 0000000000000000 001b18 0001f4 00 0 0 1 " "" "" +# Verify many section header flags display properly. +NOSPACE=1 testing "-S flags" "readelf -SW $elf-shflags | head -32" \ +"There are 28 section headers, starting at offset 0xc74: + +Section Headers: + [Nr] Name Type Address Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 000001b4 0001b4 000013 00 A 0 0 1 + [ 2] .note.android.ident NOTE 000001c8 0001c8 000018 00 A 0 0 4 + [ 3] .note.gnu.build-id NOTE 000001e0 0001e0 000020 00 A 0 0 4 + [ 4] .dynsym DYNSYM 00000200 000200 000060 10 A 8 1 4 + [ 5] .gnu.version VERSYM 00000260 000260 00000c 02 A 4 0 2 + [ 6] .gnu.version_r VERNEED 0000026c 00026c 000020 00 A 8 1 4 + [ 7] .gnu.hash GNU_HASH 0000028c 00028c 000018 00 A 4 0 4 + [ 8] .dynstr STRTAB 000002a4 0002a4 000064 00 A 0 0 1 + [ 9] .rel.dyn ANDROID_REL 00000308 000308 00000d 01 A 4 0 4 + [10] .relr.dyn RELR 00000318 000318 00000c 04 A 0 0 4 + [11] .ARM.exidx ARM_EXIDX 00000324 000324 000028 00 AL 14 0 4 + [12] .rel.plt REL 0000034c 00034c 000020 08 AI 4 19 4 + [13] .rodata PROGBITS 0000036c 00036c 000015 01 AMS 0 0 1 + [14] .text PROGBITS 00001384 000384 0001c4 00 AX 0 0 4 + [15] .plt PROGBITS 00001550 000550 000060 00 AX 0 0 16 + [16] .tdata PROGBITS 000025c0 0005c0 000000 00 WAT 0 0 32 + [17] .dynamic DYNAMIC 000025c0 0005c0 0000d0 08 WA 8 0 4 + [18] .got PROGBITS 00002690 000690 000010 00 WA 0 0 4 + [19] .got.plt PROGBITS 000026a0 0006a0 00001c 00 WA 0 0 4 + [20] .data PROGBITS 000036bc 0006bc 00000c 00 WA 0 0 4 + [21] .comment PROGBITS 00000000 0006c8 0000cc 01 MS 0 0 1 + [22] .ARM.attributes ATTRIBUTES 00000000 000794 000042 00 0 0 1 + [23] .debug_frame PROGBITS 00000000 0007d8 00007a 00 C 0 0 4 + [24] .symtab SYMTAB 00000000 000854 000220 10 26 27 4 + [25] .shstrtab STRTAB 00000000 000a74 00010e 00 0 0 1 + [26] .strtab STRTAB 00000000 000b82 0000de 00 0 0 1 + [27] .gnu_debuglink PROGBITS 00000000 000c60 000014 00 0 0 4 +" "" "" + testing "-l" "readelf -lW $elf-short" " Elf file type is DYN (Shared object file) Entry point 0x1001 diff --git a/toys/other/readelf.c b/toys/other/readelf.c index 6aaa55e1..15e5e7d7 100644 --- a/toys/other/readelf.c +++ b/toys/other/readelf.c @@ -542,7 +542,7 @@ static void scan_elf() if (FLAG(S)) { char sh_flags[12] = {}, *p = sh_flags; - for (j=0; j<12; j++) if (s.flags&(1< Date: Mon, 4 Dec 2023 04:05:46 -0600 Subject: Cleanup pass: FLAG() macros, yank unnecessary globals, whitespace/indent. --- toys/other/acpi.c | 90 +++++++++++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/toys/other/acpi.c b/toys/other/acpi.c index 3e19141c..193ac28a 100644 --- a/toys/other/acpi.c +++ b/toys/other/acpi.c @@ -24,11 +24,6 @@ config ACPI #define FOR_acpi #include "toys.h" -GLOBALS( - int ac, bat, therm, cool; - char *cpath; -) - static int read_int_at(int dirfd, char *name) { int fd, ret=0; @@ -43,101 +38,98 @@ static int read_int_at(int dirfd, char *name) static int acpi_callback(struct dirtree *tree) { - int dfd, fd, len, on; + int dfd, fd, len, on, bat = 0, ac = 0; + char *cpath; errno = 0; - if (tree->name[0]=='.') return 0; - - if (!tree->parent) - return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; + if (*tree->name=='.') return 0; + if (!tree->parent) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; - if (0 <= (dfd = open((TT.cpath=dirtree_path(tree, NULL)), O_RDONLY))) { + if (0<=(dfd = open((cpath = dirtree_path(tree, 0)), O_RDONLY))) { if ((fd = openat(dfd, "type", O_RDONLY)) < 0) goto done; len = readall(fd, toybuf, sizeof(toybuf)); close(fd); - if (len < 1) goto done; + if (len<1) goto done; if (!strncmp(toybuf, "Battery", 7)) { - if ((toys.optflags & FLAG_b) || (!toys.optflags)) { + if (FLAG(b) || !toys.optflags) { int cap = 0, curr = 0, max = 0; - if ((cap = read_int_at(dfd, "capacity")) < 0) { - if ((max = read_int_at(dfd, "charge_full")) > 0) + if ((cap = read_int_at(dfd, "capacity"))<0) { + if ((max = read_int_at(dfd, "charge_full"))>0 || + (max = read_int_at(dfd, "energy_full"))>0) curr = read_int_at(dfd, "charge_now"); - else if ((max = read_int_at(dfd, "energy_full")) > 0) - curr = read_int_at(dfd, "energy_now"); - if (max > 0 && curr >= 0) cap = 100 * curr / max; + if (max>0 && curr>=0) cap = 100*curr/max; } - if (cap >= 0) printf("Battery %d: %d%%\n", TT.bat++, cap); + if (cap>=0) printf("Battery %d: %d%%\n", bat++, cap); } - } else if (toys.optflags & FLAG_a) { - if ((on = read_int_at(dfd, "online")) >= 0) - printf("Adapter %d: %s-line\n", TT.ac++, (on ? "on" : "off")); - } + } else if (FLAG(a) && (on = read_int_at(dfd, "online"))>=0) + printf("Adapter %d: %s-line\n", ac++, on ? "on" : "off"); done: close(dfd); } - free(TT.cpath); + free(cpath); return 0; } static int temp_callback(struct dirtree *tree) { - int dfd, temp; + int dfd, temp, therm = 0; + char *cpath; if (*tree->name=='.') return 0; if (!tree->parent || !tree->parent->parent) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; errno = 0; - if (0 <= (dfd = open((TT.cpath=dirtree_path(tree, NULL)), O_RDONLY))) { + if (0<=(dfd = open((cpath = dirtree_path(tree, 0)), O_RDONLY))) { if ((0 < (temp = read_int_at(dfd, "temp"))) || !errno) { - //some tempertures are in milli-C, some in deci-C - //reputedly some are in deci-K, but I have not seen them - if (((temp >= 1000) || (temp <= -1000)) && (temp%100 == 0)) temp /= 100; - printf("Thermal %d: %d.%d degrees C\n", TT.therm++, temp/10, temp%10); + // some tempertures are in milli-C, some in deci-C + // reputedly some are in deci-K, but I have not seen them + if ((temp>=1000 || temp<=-1000) && !(temp%100)) temp /= 100; + printf("Thermal %d: %d.%d degrees C\n", therm++, temp/10, temp%10); } close(dfd); } - free(TT.cpath); + free(cpath); return 0; } static int cool_callback(struct dirtree *tree) { - int dfd=5, cur, max; + int dfd = 5, cur, max, cool = 0; + char *cpath; errno = 0; - memset(toybuf, 0, sizeof(toybuf)); + memset(toybuf, 0, 257); if (*tree->name == '.') return 0; if (!tree->parent) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; - - if (0 <= (dfd = open((TT.cpath=dirtree_path(tree, &dfd)), O_RDONLY))) { - TT.cpath = strcat(TT.cpath, "/type"); - if (readfile(TT.cpath, toybuf, 256) && !errno) { - toybuf[strlen(toybuf) -1] = 0; - cur=read_int_at(dfd, "cur_state"); - max=read_int_at(dfd, "max_state"); - if (errno) - printf("Cooling %d: %s no state information\n", TT.cool++, toybuf); - else printf("Cooling %d: %s %d of %d\n", TT.cool++, toybuf, cur, max); + if (0<=(dfd = open((cpath = dirtree_path(tree, &dfd)), O_RDONLY))) { + strcat(cpath, "/type"); + if (readfile(cpath, toybuf, 256) && !errno) { + chomp(toybuf); + cur = read_int_at(dfd, "cur_state"); + max = read_int_at(dfd, "max_state"); + printf("Cooling %d: %s ", cool++, toybuf); + if (errno) printf("no state information\n"); + else printf("%d of %d\n", cur, max); } close(dfd); } - free(TT.cpath); + free(cpath); + return 0; } void acpi_main(void) { - if (toys.optflags & FLAG_V) toys.optflags = FLAG_a|FLAG_b|FLAG_c|FLAG_t; + if (FLAG(V)) toys.optflags = FLAG_a|FLAG_b|FLAG_c|FLAG_t; if (!toys.optflags) toys.optflags = FLAG_b; - if (toys.optflags & (FLAG_a|FLAG_b)) - dirtree_read("/sys/class/power_supply", acpi_callback); - if (toys.optflags & FLAG_t) dirtree_read("/sys/class", temp_callback); - if (toys.optflags & FLAG_c) dirtree_read("/sys/class/thermal", cool_callback); + if (FLAG(a)|FLAG(b)) dirtree_read("/sys/class/power_supply", acpi_callback); + if (FLAG(t)) dirtree_read("/sys/class", temp_callback); + if (FLAG(c)) dirtree_read("/sys/class/thermal", cool_callback); } -- cgit v1.2.3 From 310c6790cb7cd5e30d5e305d9aba4e6a8116473e Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 4 Dec 2023 04:30:46 -0600 Subject: Fix truncate -8g on 32 bit. --- toys/other/truncate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toys/other/truncate.c b/toys/other/truncate.c index 7adeb62d..42ab69cb 100644 --- a/toys/other/truncate.c +++ b/toys/other/truncate.c @@ -26,7 +26,7 @@ config TRUNCATE GLOBALS( char *s; - long size; + long long size; int type; ) -- cgit v1.2.3 From c96cdc19b3791eaa0a8038b0ed2f03c6d93c747e Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 4 Dec 2023 04:35:00 -0600 Subject: Fix 32 bit lib/args.c to report out of range numeric values. Test with "skeleton -c 8g" for example. --- lib/args.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/args.c b/lib/args.c index edf06e99..c5ba4505 100644 --- a/lib/args.c +++ b/lib/args.c @@ -207,7 +207,8 @@ static void gotflag(struct getoptflagstate *gof, struct opts *opt, int longopt) *list = xzalloc(sizeof(struct arg_list)); (*list)->arg = arg; } else if (type == '#' || type == '-') { - long l = atolx(arg); + long long l = atolx(arg); + if (type == '-' && !ispunct(*arg)) l*=-1; if (l < opt->val[0].l) help_exit("-%c < %ld", opt->c, opt->val[0].l); if (l > opt->val[1].l) help_exit("-%c > %ld", opt->c, opt->val[1].l); -- cgit v1.2.3 From 992a1071e5d75e3311ccf6ccce9c2d17be157115 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 4 Dec 2023 06:52:16 -0600 Subject: Tweak help text and minor variable initialization cleanup. --- toys/other/blkdiscard.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/toys/other/blkdiscard.c b/toys/other/blkdiscard.c index 862e4fed..652d5ebd 100644 --- a/toys/other/blkdiscard.c +++ b/toys/other/blkdiscard.c @@ -14,19 +14,20 @@ config BLKDISCARD bool "blkdiscard" default y help - usage: blkdiscard [-olszf] DEVICE + usage: blkdiscard [-szf] [-o OFFSET] [-l LENGTH] DEVICE - Discard device sectors. + Discard device sectors (permanetly deleting data). Free space can improve + flash performance and lifetime by wear leveling and collating data. + (Some filesystem/driver combinations can do this automatically.) - -o, --offset OFF Byte offset to start discarding at (default 0) - -l, --length LEN Bytes to discard (default all) - -s, --secure Perform secure discard - -z, --zeroout Zero-fill rather than discard - -f, --force Disable check for mounted filesystem + -o Start at OFFSET (--offset, default 0) + -l LENGTH to discard (--length, default all) + -s Overwrite discarded data (--secure) + -z Zero-fill rather than discard (--zeroout) + -f Disable check for mounted filesystem (--force) - OFF and LEN must be aligned to the device sector size. - By default entire device is discarded. - WARNING: All discarded data is permanently lost! + OFFSET and LENGTH must be aligned to the device sector size. Default + without -o/-l discards the entire device. (You have been warned.) */ #define FOR_blkdiscard @@ -41,12 +42,10 @@ GLOBALS( void blkdiscard_main(void) { int fd = xopen(*toys.optargs, O_WRONLY|O_EXCL*!FLAG(f)); - unsigned long long ol[2]; + unsigned long long ol[2] = {TT.o, TT.l}; - // TODO: if numeric arg was long long array could live in TT. - ol[0] = TT.o; - if (FLAG(l)) ol[1] = TT.l; - else { + // TODO: argument size capped to 2 gigs on 32-bit, even with "-l 8g" + if (!FLAG(l)) { xioctl(fd, BLKGETSIZE64, ol+1); ol[1] -= ol[0]; } -- cgit v1.2.3 From 82f62a8d86a19b91cff1e264e144dd695784843c Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 4 Dec 2023 07:01:56 -0600 Subject: Minor cleanup. --- toys/other/blkid.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/toys/other/blkid.c b/toys/other/blkid.c index 951f8487..e78f20d8 100644 --- a/toys/other/blkid.c +++ b/toys/other/blkid.c @@ -197,17 +197,14 @@ static void do_blkid(int fd, char *name) if (!strcmp(type, "ntfs")) { for (j = 7; j >= 0; --j) s += sprintf(s, "%02X", toybuf[uoff+j]); } else if (!strcmp(type, "vfat")) { - s += sprintf(s, "%02X%02X-%02X%02X", toybuf[uoff+3], toybuf[uoff+2], - toybuf[uoff+1], toybuf[uoff]); + s += sprintf(s, "%02X%02X-%02X%02X", toybuf[uoff+3], toybuf[uoff+2], + toybuf[uoff+1], toybuf[uoff]); } else if (!strcmp(type, "iso9660")) { - s += sprintf(s, "%c%c%c%c-", toybuf[uoff], toybuf[uoff+1], - toybuf[uoff+2], toybuf[uoff+3]); - s += sprintf(s, "%c%c-", toybuf[uoff+4], toybuf[uoff+5]); - s += sprintf(s, "%c%c-", toybuf[uoff+6], toybuf[uoff+7]); - s += sprintf(s, "%c%c-", toybuf[uoff+8], toybuf[uoff+9]); - s += sprintf(s, "%c%c-", toybuf[uoff+10], toybuf[uoff+11]); - s += sprintf(s, "%c%c-", toybuf[uoff+12], toybuf[uoff+13]); - s += sprintf(s, "%c%c", toybuf[uoff+14], toybuf[uoff+15]); + s = stpncpy(s, toybuf+uoff, 4); + for (i = 0, uoff += 4; i<12; i++) { + if (!(i&1)) *s++ = '-'; + *s++ = toybuf[uoff++]; + } } else { for (j = 0; j < 16; j++) s += sprintf(s, "-%02x"+!(0x550 & (1< Date: Wed, 6 Dec 2023 05:16:25 -0600 Subject: A few more shell tests. --- tests/sh.test | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/sh.test b/tests/sh.test index d13acd83..306a4392 100644 --- a/tests/sh.test +++ b/tests/sh.test @@ -100,6 +100,7 @@ export EVAL="timeout 10 $SH -c" testing 'return code' 'if false; then echo true; fi; echo $?' '0\n' '' '' testing 'return code 2' 'if true; then false; fi; echo $?' '1\n' '' '' testing 'return code 3' 'x=0; while [ $((x++)) -lt 2 ]; do echo $x; done; echo $?' '1\n2\n0\n' '' '' +testing 'return code 4' 'false; A=B; echo $?' '0\n' '' '' testing 'local var +whiteout' \ 'l=X;x(){ local l=47; echo $l;unset l; echo l=$l;};x;echo $l' '47\nl=\nX\n' \ '' '' @@ -107,18 +108,34 @@ testing 'escape passthrough' 'echo -e "a\nb\nc\td"' 'a\nb\nc\td\n' '' '' testing 'trailing $ is literal' 'echo $' '$\n' '' '' testing 'work after HERE' $'cat<<0;echo hello\npotato\n0' 'potato\nhello\n' '' '' +testing '<<\EOF' $'(cat</dev/null\nabcde\nnext\\\nEOF\nEOF' \ 'abcde\nnextEOF\n' '' '' testing '<< trailing \ 2' $'cat< ' I$'> blah\n' E"$P" \ shxpect 'line continuation2' I$'echo ABC\\\n' E'> ' I$'DEF\n' O$'ABCDEF\n' testing "line continuation3" $'ec\\\nho hello' 'hello\n' '' '' testing "line continuation4" $'if true | \\\n(true);then echo true;fi' 'true\n' '' '' +testing "line continuation5" $'XYZ=xyz; echo "abc$\\\nXYZ"' 'abcxyz\n' '' '' # Race condition (in bash, but not in toysh) can say 43. testing 'SECONDS' 'readonly SECONDS=41; sleep 1; echo $SECONDS' '42\n' '' '' @@ -696,6 +719,9 @@ testing 'quoting contexts nest' \ $'echo -n "$(echo "hello $(eval $\'echo -\\\\\\ne \\\'world\\n \\\'\')")"' \ 'hello world\n ' '' '' +testing 'if; is a syntax error but if $EMPTY; is not' \ + 'if $NONE; then echo hello; fi' 'hello\n' '' '' + # TODO finish variable list from shell init # $# $? $- $! $0 # $$ -- cgit v1.2.3