ctfconv/DWARF & clang static variables
When a static variable is defined in a function, clang(1) emits the following DWARF: <1><90>: Abbrev Number: 9 (DW_TAG_subprogram) DW_AT_name: (indirect string, offset: 0x213b): pageflttrap [...] <2>: Abbrev Number: 10 (DW_TAG_variable) DW_AT_name: (indirect string, offset: 0xc9): faultbuf [...] <2>: Abbrev Number: 11 (DW_TAG_formal_parameter) DW_AT_name: (indirect string, offset: 0x217d): frame [...] <2>: Abbrev Number: 11 (DW_TAG_formal_parameter) DW_AT_name: (indirect string, offset: 0x2183): usermode [...] As you can see the function arguments are placed *after* the local static variable. ctfconv(1) currently stops parsing a `DW_TAG_subprogram' section as soon as it find a variable definition. That means with modern clang(1) functions like panic(9) or pageflttrap() are incorrectly identified as having no argument. Diff below fixes that, ok? Index: parse.c === RCS file: /cvs/src/usr.bin/ctfconv/parse.c,v retrieving revision 1.11 diff -u -p -r1.11 parse.c --- parse.c 31 Jan 2018 14:47:13 - 1.11 +++ parse.c 6 Nov 2019 13:43:32 - @@ -1138,12 +1142,19 @@ subparse_arguments(struct dwdie *die, si * Nested declaration. * * This matches the case where a ``struct'', ``union'', -* ``enum'' or ``typedef'' is first declared "inside" a -* function declaration. +* ``enum'', ``typedef'' or ``static'' variable is first +* declared inside a function declaration. */ - if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type || - tag == DW_TAG_enumeration_type || tag == DW_TAG_typedef) + switch (tag) { + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_variable: continue; + default: + break; + } if (tag != DW_TAG_formal_parameter) break;
Re: Stop using static variables in ICMP
On 9 August 2013 11:04, Martin Pieuchot wrote: > This is the last episode from the first season of the serie, "move > your variables to the stack". Like in the previous episodes, this > one will let us execute the various icmp functions in parallel > without risk of trashing a value. > > It also reduces the difference with the icmp6 code adding a redirect > route. > > ok? > OK
Stop using static variables in ICMP
This is the last episode from the first season of the serie, "move your variables to the stack". Like in the previous episodes, this one will let us execute the various icmp functions in parallel without risk of trashing a value. It also reduces the difference with the icmp6 code adding a redirect route. ok? Index: netinet/ip_icmp.c === RCS file: /home/ncvs/src/sys/netinet/ip_icmp.c,v retrieving revision 1.104 diff -u -p -r1.104 ip_icmp.c --- netinet/ip_icmp.c 8 Aug 2013 14:59:22 - 1.104 +++ netinet/ip_icmp.c 9 Aug 2013 08:40:27 - @@ -297,10 +297,6 @@ icmp_error(struct mbuf *n, int type, int icmp_send(m, NULL); } -struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET }; -static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET }; -static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; - /* * Process a received ICMP message. */ @@ -309,14 +305,11 @@ icmp_input(struct mbuf *m, ...) { struct icmp *icp; struct ip *ip = mtod(m, struct ip *); - int icmplen; - int i; + struct sockaddr_in sin; + int icmplen, i, code, hlen; struct in_ifaddr *ia; void *(*ctlfunc)(int, struct sockaddr *, u_int, void *); - int code; - int hlen; va_list ap; - struct rtentry *rt; struct mbuf *opts; va_start(ap, m); @@ -479,10 +472,13 @@ icmp_input(struct mbuf *m, ...) if (icmpprintfs) printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); #endif - icmpsrc.sin_addr = icp->icmp_ip.ip_dst; + bzero(&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(struct sockaddr_in); + sin.sin_addr = icp->icmp_ip.ip_dst; #if NCARP > 0 if (m->m_pkthdr.rcvif->if_type == IFT_CARP && - carp_lsdrop(m, AF_INET, &icmpsrc.sin_addr.s_addr, + carp_lsdrop(m, AF_INET, &sin.sin_addr.s_addr, &ip->ip_dst.s_addr)) goto freeit; #endif @@ -492,7 +488,7 @@ icmp_input(struct mbuf *m, ...) */ ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; if (ctlfunc) - (*ctlfunc)(code, sintosa(&icmpsrc), m->m_pkthdr.rdomain, + (*ctlfunc)(code, sintosa(&sin), m->m_pkthdr.rdomain, &icp->icmp_ip); break; @@ -538,14 +534,17 @@ icmp_input(struct mbuf *m, ...) * We are not able to respond with all ones broadcast * unless we receive it over a point-to-point interface. */ + bzero(&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(struct sockaddr_in); if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_dst.s_addr == INADDR_ANY) - icmpdst.sin_addr = ip->ip_src; + sin.sin_addr = ip->ip_src; else - icmpdst.sin_addr = ip->ip_dst; + sin.sin_addr = ip->ip_dst; if (m->m_pkthdr.rcvif == NULL) break; - ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst), + ia = ifatoia(ifaof_ifpforaddr(sintosa(&sin), m->m_pkthdr.rcvif)); if (ia == 0) break; @@ -579,6 +578,12 @@ reflect: return; case ICMP_REDIRECT: + { + struct sockaddr_in sdst; + struct sockaddr_in sgw; + struct sockaddr_in ssrc; + struct rtentry *newrt = NULL; + /* Free packet atttributes */ if (m->m_flags & M_PKTHDR) m_tag_delete_chain(m); @@ -598,8 +603,15 @@ reflect: * listening on a raw socket (e.g. the routing * daemon for use in updating its tables). */ - icmpgw.sin_addr = ip->ip_src; - icmpdst.sin_addr = icp->icmp_gwaddr; + bzero(&sdst, sizeof(sdst)); + bzero(&sgw, sizeof(sgw)); + bzero(&ssrc, sizeof(ssrc)); + sdst.sin_family = sgw.sin_family = ssrc.sin_family = AF_INET; + sdst.sin_len = sgw.sin_len = ssrc.sin_len = sizeof(sdst); + bcopy(&icp->icmp_ip.ip_dst, &sdst.sin_addr, sizeof(sdst)); + bcopy(&icp->icmp_gwaddr, &sgw.sin_addr, sizeof(sgw)); + bcopy(&ip->ip_src, &ssrc.sin_addr, sizeof(ssrc)); + #ifdef ICMPPRINTFS if (icmpprintfs) { char buf[4 * sizeof("123")]; @@ -610,27 +622,25 @@ reflect: buf, inet_ntoa(icp->icmp_gwaddr));
Re: Static variables
On Mon, Jul 8, 2013 at 2:06 AM, Maxime Villard wrote: > Ah, yes. I didn't know. For what it's worth, this is specified in C99 §6.7.8 (Initializaton) paragraph 10: "If an object that has static storage duration is not initialized explicitly, then: — if it has pointer type, it is initialized to a null pointer; — if it has arithmetic type, it is initialized to (positive or unsigned) zero; — if it is an aggregate, every member is initialized (recursively) according to these rules; — if it is a union, the first named member is initialized (recursively) according to these rules." On OpenBSD (and most, if not all, ELF platforms), this is implemented by assigning these objects into the .bss section, which is initialized to all zero bytes at program startup, taking advantage of the fact that all of our platforms represent null pointers and zero values as sequences of zero bytes.
Re: Static variables
Le 08/07/2013 11:00, Franco Fichtner a écrit : > Hi Maxime, > > On Jul 8, 2013, at 10:40 AM, Maxime Villard wrote: > >> the static variables are not initialized? > > Static variables are always zeroed when not specified otherwise. > > > Regards, > Franco > > Ah, yes. I didn't know.
Re: Static variables
Hi Maxime, On Jul 8, 2013, at 10:40 AM, Maxime Villard wrote: > the static variables are not initialized? Static variables are always zeroed when not specified otherwise. Regards, Franco
Static variables
Hi, is it normal that in some functions like tc_ticktock(void) { static int count; if (++count < tc_tick) return; count = 0; tc_windup(); } the static variables are not initialized? - kern_tc.c l.547 - kern_resource.c l.499 - kern_sched.c l.106 - subr_extent.c l.130 - ...