I was looking at memory use of going through all kernel modules with
libdwfl in systemtap. My local kernel install has almost 2000 modules.
We can probably do some stuff in systemtap, but I happened to see that
each Dwfl_Module keeps a reference to the ebl for the module elf machine
Couldn't these ebls be shared in the Dwfl for the Dwfl_Modules? So only
the first Dwfl_Module that needs it, calls __libdwfl_module_getebl(),
has to call ebl_openbackend() and then store it in the Dwfl structure?
Could different Dwfl_Modules from the same Dwfl have different elf
machine types? Or does an ebl keep state that cannot be shared?
Here is a patch that adds additional support for the arm backend.
One of the things it does it add support to see the difference
between hard and soft floating point operations. Currently this
is done by selecting a different return_value_location hook,
which probably isn't a good long term solution, but the only
way I can see without having to change all the backends.
Most of this patch was written by
Eugeniy Meshcheryakov <eugeniy.meshcheryakov(a)googlemail.com>
with some minor changes from me.
I've just noticed two bad things. One is that in the elfutils-0.142 state
(commit 2f5b79e9348c651604795452fb4831964b3917b1, which is what the
official 0.142 tarball got), elfutils.spec.in lacks its 0.142 entry.
The other is that elfutils-0.142 is an "unannotated" tag. It should be a
signed tag. i.e., it looks like it was made with "git tag elfutils-0.142",
but should have been "git tag -s elfutils-0.142". This makes e.g. "git
describe" refer to 0.140 instead of 0.142 for all the revs since then.
I'm wondering if maybe you have some lost head locally where you committed
elfutils.spec.in and never pushed it. If so, you could just merge that I
guess. (But I wouldn't use that new head to replace the elfutils-0.142
tag. That tarball is already baked.)
But anyway, I think you should do:
GIT_COMMITTER_DATE=2009-06-29 git tag -f -s elfutils-0.142 elfutils-0.142
git push -f origin tag elfutils-0.142
I'd like to ask you to reconsider merging the robustify branch.
It prevents crashes, buffer overruns, and confusions resulting
from extremely bogus ELF header data in input files, such as
fields that could cause integer overflow.
In the past you said that you did not want libelf and utilities
to add any code to cope with abjectly bogus data. I take it your
sentiment is that you should just not work with ELF files of
untrusted origin, ever. In many ways I think that is quite
reasonable, but in practice it's not always feasible to avoid
even looking at some unknown file. Things happen, and people
lose track of where things came from, and can't always just toss
them when they are not sure. I think it is reasonable to expect
to have a robust tool that tells you whether a file is too bogus
to look at or not.
Fedora and RHEL have been carrying this patch (and will) forever,
so it's in the code that everybody is actually using anyway.
In my -O2 build (F11/x86_64) it bloats libelf's text by 0.83%,
elflint's by 0.56%, readelf's by 0.40%, and strip's by 0.07%.
elflint is the tool you use to decide whether an ELF file is safe
to work with or is too bogus to feed to anything else. readelf
is the tool you use to figure out exactly what's wrong with it,
whether diagnosing build tool bugs or investigating an actual
maliciously composed bogus binary.
libelf is the common dependency that elflint and readelf both
must rely on for the lowest-level bits of their robustness.
libelf is also the only part of our suite that is used in an
unknown variety of third-party and user applications that may
have expectations of robust diagnosis of all possible bad input
data (which is a fairly normal expectation out there).
strip is something that nobody should apply to random unknown
binaries. But we have real-world experience from admins
(misguided as they may be) blindly applying it to ELF files,
likely being stupid enough to do that in privileged situations,
and being unnerved by the possibility of strip being exploited
with buffer overruns in maliciously composed bogus ELF files.
And anyway, 0.07%.
Since the gcc vta branch now emits the new (Dwarf 4) DW_OP_stack_value
and DW_OP_implicit_value operands I looked into supporting them. This is
a little bit difficult since, especially DW_OP_implicit_value changes
some assumptions (at least some of mine).
Unlike what the current comment in dwarf.h says the value block of
DW_OP_implicit_value isn't carried in a DW_FORM, but uses the "raw
memory encoding of the target". At least that is what gcc seems to emit,
and reading the spec, that does seem what was meant to happen. This is
somewhat awkward since it means we don't have the context to interpret
the value at this point. You could see what points to the location
description and see what the type should be, but that might not always
be simple, so you have to depend on the caller knowing what to do with
the "raw memory encoding".
2009-07-19 Mark Wielaard <mjw(a)redhat.com>
* dwarf.h: Correct description of DW_OP_implicit_value encoding.
Making readelf support them isn't too hard. For DW_OP_stack_value it is
simply listing the new opcode. For DW_OP_implicit_value it means just
reading the length and the (non-encoded) value. The only difficult is
whether or not the try to print the value in a decoded form when the
length is known. My patch prints it decoded when it is [1,] 2, 4 or 8
bytes since it is most likely to be a value of a basic type, otherwise
it just dumps it as a hex bytes as is.
2009-07-19 Mark Wielaard <mjw(a)redhat.com>
* readelf.c (print_ops): Add handling of DW_OP_implicit_value
Then we come to libdw getlocation() and things get a bit harder. Again
DW_OP_stack_value isn't much trouble. It doesn't have any operands, so
just return it as is when interning. But DW_OP_implicit_value is a bit
of an issue, since we don't know the actual value (no DW_FORM, just raw
bytes), there is no convenient way to store it. Also it can be of
arbitrary length, and all we have are two Dwarf_Words. In theory we
could just pass the length and the offset (already there in the
Dwarf_Op) into the Dwarf_Block. But there are two issues with this.
First, the offset is to the start of the DW_OP and there is no
convenient way I know of for the caller to get the size of the length
encoding, so it is hard to determine the actual offset (we could store
the extra offset/length-size in the number2 Dwarf_Word though).
Secondly I don't actually understand how the caller would get a handle
to the Dwarf_Block the offset refers to. For dwarf_getlocation() it
would be easy, just call dwarf_formblock() on the Dwarf_Attribute. But
for dwarf_getlocation_addr() the caller would have to parse the location
list themselves and hope they do it in the same order/preference that
dwarf_getlocation_addr() does it. Or am I missing some simple method to
get at the Dwarf_Block that the Dwarf_Op array that
dwarf_getlocation_addr() returns refer to?
So for now I just store the length as number and the actual address into
the Dwarf_Block data where the raw memory representation starts into
number2. But this feels a bit like cheating, since it isn't really
interning the DW_OP data since it depends on having the pointer into the
2009-07-20 Mark Wielaard <mjw(a)redhat.com>
* dwarf_getlocation.c (__libdw_intern_expression): Handle
DW_OP_stack_value and DW_OP_implicit_value.
Just a small trivial query: addr2line considers address as decimal by
default unless one adds 0x . Usually we have address in hexadecimal.
Does it makes sense to make hexadecimal default (so that one does not
need an extra 0x) ?
freedom, friends, features, first