You can do what you do for C++ vtable output, use the linkage rules to
determine a single place, or a few places, that debug information
might need to be output.
For instance, you could do it like this: A given piece of debugging
information need not be placed in a .o file if the lexicographically
first external symbol used by the .o file, whose debugging information
requires that piece of information, is not defined in the same .o
file. That is, in
struct x { int y; };
extern int bar (struct x *);
int foo (void) {
struct x tt = { 3 };
return bar(&tt);
}
we decide that because 'bar' is alphabetically before 'foo',
everything to do with 'bar' will already be output in its .o file, so
we don't have to output any of it here (including the definition of
'struct x'). For C++, you would decide that vtable definitions come
"before" everything else, so debug information gets output with the
vtable if there is one.
The idea is that it doesn't need to be perfect, since duplicate
information is harmless; just so long as you can eliminate most of the
duplicates.