egcs/linux networking problem isolated

Alan Modra (alan@spri.levels.unisa.edu.au)
Wed, 14 Apr 1999 00:48:34 +0930 (CST)


I bootstrapped egcs-2.93.17 the other evening and tried compiling
linux-2.2.5 for i586. It was rather disconcerting to find networking
completely broken; even "ping localhost" failed... Scanned the egcs-bugs
archive to find this is a known problem with recent snapshots, but not
resolved yet.

Anyway, to cut a long story short, after much recompiling with gcc-2.7.2
and egcs, I narrowed the problem down to a memcpy in
linux/net/ipv4/ip_output.c

Here's an extract from the source:

int ip_output(struct sk_buff *skb)
{
#ifdef CONFIG_IP_ROUTE_NAT
struct rtable *rt = (struct rtable*)skb->dst;
#endif

ip_statistics.IpOutRequests++;

#ifdef CONFIG_IP_ROUTE_NAT
if (rt->rt_flags&RTCF_NAT)
ip_do_nat(skb);
#endif

return ip_finish_output(skb);
}

with ip_finish_output defined in linux/include/net/ip.h

extern __inline__ int ip_finish_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct device *dev = dst->dev;
struct hh_cache *hh = dst->hh;

skb->dev = dev;
skb->protocol = __constant_htons(ETH_P_IP);

if (hh) {
read_lock_irq(&hh->hh_lock);
memcpy(skb->data - 16, hh->hh_data, 16);
read_unlock_irq(&hh->hh_lock);
skb_push(skb, dev->hard_header_len);
return hh->hh_output(skb);
} else if (dst->neighbour)
return dst->neighbour->output(skb);

kfree_skb(skb);
return -EINVAL;
}

egcs generated code from the above memcpy

3a2: 85 f6 test %esi,%esi
3a4: 74 5a je 400 <ip_output+0x80>
3a6: fa cli # read_lock_irq
3a7: 8b 8b 80 00 00 00 mov 0x80(%ebx),%ecx
3ad: 8d 56 10 lea 0x10(%esi),%edx
3b0: 8b 46 10 mov 0x10(%esi),%eax
3b3: 89 41 f0 mov %eax,0xfffffff0(%ecx)
3b6: 8b 42 04 mov 0x4(%edx),%eax
3b9: 89 41 f4 mov %eax,0xfffffff4(%ecx)
3bc: 8b 42 08 mov 0x8(%edx),%eax
3bf: 89 41 f8 mov %eax,0xfffffff8(%ecx)
3c2: 8b 42 0c mov 0xc(%edx),%eax
3c5: 89 41 fc mov %eax,0xfffffffc(%ecx)
3c8: fb sti # read_unlock_irq

gcc-2.7.2 generated code

367: 85 f6 test %esi,%esi
369: 74 53 je 3be <ip_output+0x75>
36b: fa cli
36c: 8b 93 80 00 00 00 mov 0x80(%ebx),%edx
372: 8b 46 14 mov 0x14(%esi),%eax
375: 89 42 f0 mov %eax,0xfffffff0(%edx)
378: 8b 46 18 mov 0x18(%esi),%eax
37b: 89 42 f4 mov %eax,0xfffffff4(%edx)
37e: 8b 46 1c mov 0x1c(%esi),%eax
381: 89 42 f8 mov %eax,0xfffffff8(%edx)
384: 8b 46 20 mov 0x20(%esi),%eax
387: 89 42 fc mov %eax,0xfffffffc(%edx)
38a: fb sti

Notice how the read locations are off! egcs reads from 0x10(%esi) to
0x1c(%esi), while gcc-2.7.2 reads from 0x14(%esi) to 0x20(%esi).

cc'd to linux-kernel for general interest - this one doesn't look like
a linux bug. Hope there's enough info here for egcs gurus to squash this
one.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/