[LLVMdev] asan coverage

Duncan P. N. Exon Smith dexonsmith at apple.com
Mon Mar 31 15:13:21 PDT 2014


On Mar 31, 2014, at 10:45, Bob Wilson <bob.wilson at apple.com> wrote:

> 
> On Mar 31, 2014, at 1:53 AM, Kostya Serebryany <kcc at google.com> wrote:
>> 
>> This is what I see on 483.xalancbmk:
>>  15 __llvm_prf_names 0036fcb0  00000000010abf40  00000000010abf40  00cabf40  2**5
>>  16 __llvm_prf_data 001b77e0  000000000141bc00  000000000141bc00  0101bc00  2**5
>>  32 __llvm_prf_cnts 00123468  0000000001af2fe0  0000000001af2fe0  014f2fe0  2**5
>> 
>> __llvm_prf_names is larger than the other two combined. 
>> 483.xalancbmk is C++ and the function names are long. The same is true for most of the code we care about.
>> Can't we use function PCs instead of function names in this table (and retrieve the function names from debug info)?
> 
> That’s a bit surprising. We should check to make sure there isn’t anything obviously wrong.

I'm surprised too, but it makes some sense.

  - Most functions in the implementation details of the STL have long enough mangled
    names (and little enough control flow) that the names would dominate the size
    overhead.

  - Many class member functions will have this property, too, like getters, setters,
    and typical constructors, copy/move operators, and destructors.

There's likely a way to emit these names more compactly using a tree (with links
to parent nodes).

Consider _ZN9Namespace5Class3fooEv, the mangled name for Namespace::Class::foo().
We could do something like this:

    %__llvm_profile_name = type {i8*, %__llvm_profile_name*}

    @__llvm_profile_str__ZN = linkonce constant [4 x i8] c"_ZN\00"
    @__llvm_profile_name__ZN = linkonce constant %__llvm_profile_name {
      i8* getelementptr ([4 x i8]* @__llvm_profile_str__ZN, i32 0, i32 0),
      %__llvm_profile_name* null }

    @__llvm_profile_str_9Namespace = linkonce constant [11 x i8] c"9Namespace\00"
    @__llvm_profile_name__ZN9Namespace = linkonce constant %__llvm_profile_name {
      i8* getelementptr ([11 x i8]* @__llvm_profile_str_9Namespace, i32 0, i32 0),
      %__llvm_profile_name* @__llvm_profile_name__ZN }

    @__llvm_profile_str_5Class = linkonce constant [7 x i8] c"5Class\00"
    @__llvm_profile_name__ZN9Namespace5Class = linkonce constant
      %__llvm_profile_name {
      i8* getelementptr ([7 x i8]* @__llvm_profile_str_5Class, i32 0, i32 0),
      %__llvm_profile_name* @__llvm_profile_name__ZN9Namespace }

    @__llvm_profile_str_3fooEv = linkonce constant [7 x i8] c"3fooEv\00"
    @__llvm_profile_name__ZN9Namespace5Class3fooEv = linkonce constant
      %__llvm_profile_name {
      i8* getelementptr ([7 x i8]* @__llvm_profile_str_3fooEv, i32 0, i32 0),
      %__llvm_profile_name* @__llvm_profile_name__ZN9Namespace5Class }

Then _ZN9Namespace5Class3barEv (Namespace::Class::bar()) would be cheap.

    @__llvm_profile_str_3barEv = linkonce constant [7 x i8] c"3barEv\00"
    @__llvm_profile_name__ZN9Namespace5Class3barEv = linkonce constant
      %__llvm_profile_name {
      i8* getelementptr ([7 x i8]* @__llvm_profile_str_3barEv, i32 0, i32 0),
      %__llvm_profile_name* @__llvm_profile_name__ZN9Namespace5Class }

These would merge cleanly even between object files generated from different
translation units.

Doing it like that requires understanding the mangling and wouldn't compact common
prefixes in C.  We could do something similar with a heuristic (split every 8
characters), or split on common prefixes per translation unit (and hope they line up
between translation units).





More information about the llvm-dev mailing list