How to print details of dns_name_t* when hitting a gdb breakpoint in dns_name_equal
Petr Špaček
pspacek at isc.org
Wed Dec 4 20:41:01 UTC 2024
On 04. 12. 24 17:31, Kees Bakker wrote:
> On 03-12-2024 15:56, Petr Špaček wrote:
>> On 03. 12. 24 11:36, Kees Bakker via bind-users wrote:
>>> I have a CentOS FreeIPA setup with with multiple named (bind9 9.16.23)
>>> servers.
>>> On two of my five servers, when I start named it fails a REQUIRE in
>>> dns_name_equal
>>>
>>> /*
>>> * Either name1 is absolute and name2 is absolute, or neither is.
>>> */
>>> REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
>>> (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
>>>
>>> My question: if I run gdb and break in "assertion_failed", then "go up",
>>> how can I print name1 and name2 in a meaningful manner,
>>> so that I can figure out what entries are causing this failure?
>>>
>>> Just doing "p *name1" in gdb isn't very helpful for that.
>>
>> Many years ago I wrote
>> https://github.com/pspacek/bind-gdb-pretty-printers
>> to help with this problem. I have no idea if it still works, but it
>> might be worth a try, given the ancient version you are running!
> Thanks
> I got that to work after some refactoring gen_json_dict.py (I'll send
> it to your Github)
> I see that the pretty printers can help displaying dns_name_t variables.
>
> Unfortunately, I still can't make heads or tails from the name1 and name2
> at the moment of the crash.
>
> [Switching to Thread 0x7fffef88e640 (LWP 322823)]
>
> Thread 2.13 "isc-net-0011" hit Breakpoint 1, assertion_failed
> (file=0x7ffff7dd4ffe "../../../lib/dns/name.c", line=668,
> type=isc_assertiontype_require, cond=0x7ffff7dd5770 "(name1-
> >attributes & 0x00000001) == (name2->attributes & 0x00000001)")
> at ../../../bin/named/main.c:208
> 208 const char *cond) {
> (gdb) up
> #1 0x00007ffff7e9a4e0 in isc_assertion_failed
> (file=file at entry=0x7ffff7dd4ffe "../../../lib/dns/name.c",
> line=line at entry=668,
> type=type at entry=isc_assertiontype_require,
> cond=cond at entry=0x7ffff7dd5770 "(name1->attributes & 0x00000001) ==
> (name2->attributes & 0x00000001)")
> at ../../../lib/isc/assertions.c:46
> 46 isc_assertion_failed_cb(file, line, type, cond);
> (gdb)
> #2 0x00007ffff7c9fb4a in dns_name_equal (name1=<optimized out>,
> name2=<optimized out>) at ../../../lib/dns/name.c:668
> 668 REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
> (gdb)
> #3 0x00007ffff7cb4adc in match (name2=0x7fffd8650010,
> name1=0x7fffd806fca0) at ../../../lib/dns/order.c:96
> 96 return (dns_name_equal(name1, name2));
> (gdb) p *name1
> $10 = {magic = 1145983854, ndata = 0x7fffd8066010 "", length = 0, labels
> = 0, attributes = 0, offsets = 0x7fffd806fcf8 "",
> buffer = 0x0, link = {prev = 0x0, next = 0x0}, list = {head =
> 0x7fffd8073a90, tail = 0x7fffd8073a90}, ht = 0x0}
> (gdb) p *name2
> $11 = {magic = 1145983854, ndata = 0x7fffd8650128 "", length = 1, labels
> = 1, attributes = 1, offsets = 0x7fffd8650068 "",
> buffer = 0x7fffd86500e8, link = {prev = 0xffffffffffffffff, next =
> 0xffffffffffffffff}, list = {head = 0x0, tail = 0x0}, ht = 0x0}
LOL. It seems that it *somehow* got two names:
- name1 = empty relative name (equivalent to @ in a zone file)
- name2 - the root zone name (.)
Obviously comparing relative and absolute name does not make sense so it
crashes on assert. The assert works as intended ;-)
Now more seriously - you will need to track down source of the two names
and find out how they got generated.
>>> BTW My work around is to keep restarting named until it no longer fails
>>> on that REQUIRE.
It sounds like you are able to reproduce it fairly easily, right?
If that's the case I would recommend running `named` under RR debugger.
In case you are not familiar with it have a look at
https://rr-project.org/ - it is an _awesome_ debugger
Once you get `rr record` functional on your system (which might require
a bit of fiddling, but definitely worth it!) ... go and modify command
to run BIND from:
named -c ...
to something like:
rr record named -n1 -g -c ...
Then try long enough until it crashes.
If you manage to crash it under RR you basically won already. It allows
you to step back and forth in the _recording_ until you find the two
sources of names - which should shed light on the root cause.
`(gdb) watch -l` and
`(gdb) reverse-continue`
might be of use.
Good luck!
P.S. I'm eager to hear more about this journey, but perhaps e-mail me
privately? I guess the rest of bind-users might not want to hear all the
gory details.
--
Petr Špaček
Internet Systems Consortium
More information about the bind-users
mailing list