Skip to content

Commit 46cec35

Browse files
committed
fprintf: Fix division by zero for uninitialized conf_fprintf->cacheline_size field
tldr; gdb pfunct (gdb) run --compile tcp.o Program received signal SIGFPE, Arithmetic exception. 0x00007ffff7f18551 in class__fprintf_cacheline_boundary (conf=0x7fffffffda10, offset=0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1319 1319 uint32_t cacheline = offset / conf->cacheline_size; (gdb) bt #0 0x00007ffff7f18551 in class__fprintf_cacheline_boundary (conf=0x7fffffffda10, offset=0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1319 #1 0x00007ffff7f16af2 in class_member__fprintf (member=0x45de10, union_member=false, type=0x45dfb0, cu=0x435a40, conf=0x7fffffffda10, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:869 #2 0x00007ffff7f1717b in struct_member__fprintf (member=0x45de10, type=0x45dfb0, cu=0x435a40, conf=0x7fffffffda10, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:983 #3 0x00007ffff7f1945c in __class__fprintf (class=0x45dcc0, cu=0x435a40, conf=0x7fffffffdbb0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1583 #4 0x00007ffff7f1a6bd in tag__fprintf (tag=0x45dcc0, cu=0x435a40, conf=0x7fffffffdc70, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1906 #5 0x00007ffff7fbf022 in type__emit (tag=0x45dcc0, cu=0x435a40, prefix=0x0, suffix=0x0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:333 #6 0x00007ffff7fbed3d in tag__emit_definitions (tag=0x6b21e0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:265 #7 0x00007ffff7fbef45 in type__emit_definitions (tag=0x6b20c0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:315 #8 0x00007ffff7fbed15 in tag__emit_definitions (tag=0x6b3b40, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:264 #9 0x00007ffff7fbef45 in type__emit_definitions (tag=0x6b31d0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:315 #10 0x00007ffff7fbed15 in tag__emit_definitions (tag=0x4cb920, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:264 #11 0x00007ffff7fbef45 in type__emit_definitions (tag=0x4cb7d0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:315 #12 0x0000000000403592 in function__emit_type_definitions (func=0x738ad0, cu=0x435a40, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/pfunct.c:353 #13 0x0000000000403670 in function__show (func=0x738ad0, cu=0x435a40) at /var/home/acme/git/pahole/pfunct.c:371 #14 0x00000000004038e9 in cu_function_iterator (cu=0x435a40, cookie=0x0) at /var/home/acme/git/pahole/pfunct.c:404 #15 0x00007ffff7f1296b in cus__for_each_cu (cus=0x4369e0, iterator=0x403869 <cu_function_iterator>, cookie=0x0, filter=0x0) at /var/home/acme/git/pahole/dwarves.c:1919 #16 0x000000000040432a in main (argc=3, argv=0x7fffffffe1f8) at /var/home/acme/git/pahole/pfunct.c:776 (gdb) p conf->cacheline_size $2 = 0 We need to pass a conf_fprintf pointer to the chain starting with function__emit_type_definitions(), i.e. dwarves_emit.c needs to receive the printing configuration instead of, right at type__emit() synthesize a conf_fprintf without initializing conf_fprintf->cacheline_size which ends up in a division by zero. But to fix this quicker just add a helper that checks if it is zero and uses the conf_fprintf__defaults.cacheline_size field that is being initialized by all tools via: dwarves__resolve_cacheline_size(&conf_load, 0); Fixes: 772725a ("dwarves_fprintf: Move cacheline_size into struct conf_fprintf") Cc: Douglas Raillard <[email protected]> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 73383b3 commit 46cec35

File tree

1 file changed

+24
-4
lines changed

1 file changed

+24
-4
lines changed

dwarves_fprintf.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,30 @@ static struct conf_fprintf conf_fprintf__defaults = {
148148

149149
const char tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
150150

151+
/*
152+
* In dwarves_emit.c we can call type__emit() using a locally setup conf_fprintf for which
153+
* the conf->cacheline_size member is not setup and is thus zero, so check for that and
154+
* use the default one for that case.
155+
*
156+
* We really need to make the *_emit*() methods to receive a conf_fprintf pointer for
157+
* which conf->cacheline_size is set, all tools call:
158+
*
159+
* dwarves__resolve_cacheline_size(&conf_load, 0);
160+
*
161+
* To have a conf_load/conf_fprintf with that resolved, but that is not being passed to
162+
* the *_emit*() routines, duh.
163+
*
164+
* Fixing this properly will entail a series of patches, so to fix this problem
165+
* more quickly add this helper.
166+
*/
167+
static uint16_t conf_fprintf__cacheline_size(const struct conf_fprintf *conf)
168+
{
169+
return conf->cacheline_size ?: conf_fprintf__defaults.cacheline_size;
170+
}
151171

152172
size_t tag__nr_cachelines(const struct conf_fprintf *conf, const struct tag *tag, const struct cu *cu)
153173
{
154-
return (tag__size(tag, cu) + conf->cacheline_size - 1) / conf->cacheline_size;
174+
return (tag__size(tag, cu) + conf_fprintf__cacheline_size(conf) - 1) / conf_fprintf__cacheline_size(conf);
155175
}
156176

157177
static const char *tag__accessibility(const struct tag *tag)
@@ -1316,11 +1336,11 @@ static size_t class__fprintf_cacheline_boundary(struct conf_fprintf *conf,
13161336
FILE *fp)
13171337
{
13181338
int indent = conf->indent;
1319-
uint32_t cacheline = offset / conf->cacheline_size;
1339+
uint32_t cacheline = offset / conf_fprintf__cacheline_size(conf);
13201340
size_t printed = 0;
13211341

13221342
if (cacheline > *conf->cachelinep) {
1323-
const uint32_t cacheline_pos = offset % conf->cacheline_size;
1343+
const uint32_t cacheline_pos = offset % conf_fprintf__cacheline_size(conf);
13241344
const uint32_t cacheline_in_bytes = offset - cacheline_pos;
13251345

13261346
if (cacheline_pos == 0)
@@ -1762,7 +1782,7 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
17621782
}
17631783
printed += fprintf(fp, " */\n");
17641784
}
1765-
cacheline = (cconf.base_offset + type->size) % conf->cacheline_size;
1785+
cacheline = (cconf.base_offset + type->size) % conf_fprintf__cacheline_size(conf);
17661786
if (cacheline != 0)
17671787
printed += fprintf(fp, "%.*s/* last cacheline: %u bytes */\n",
17681788
cconf.indent, tabs,

0 commit comments

Comments
 (0)