lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <55C16DC7.70408@huawei.com>
Date:	Wed, 5 Aug 2015 09:58:31 +0800
From:	"Wangnan (F)" <wangnan0@...wei.com>
To:	Alexei Starovoitov <ast@...mgrid.com>,
	He Kuang <hekuang@...wei.com>, pi3orama <pi3orama@....com>
CC:	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	<llvmdev@...uiuc.edu>
Subject: Re: Cc llvmdev: Re: llvm bpf debug info. Re: [RFC PATCH v4 3/3] bpf:
 Introduce function for outputing data to perf event



On 2015/8/4 17:01, Wangnan (F) wrote:
> For people who in llvmdev:
>
> This mail is belong to a thread in linux kernel mailing list, the 
> first message
> can be retrived from:
>
>  http://lkml.kernel.org/r/55B1535E.8090406@plumgrid.com
>
> Our goal is to fild a way to make BPF program get an unique ID for 
> each type
> so it can pass the ID to other part of kernel, then we can retrive the 
> type and
> decode the structure using DWARF information. Currently we have two 
> problem
> needs to solve:
>
> 1. Dwarf information generated by BPF backend lost all DW_AT_name field;
>
> 2. How to get typeid from local variable? I tried llvm.eh_typeid_for
>    but it support global variable only.
>
> Following is my response to Alexei.
>
> On 2015/8/4 3:44, Alexei Starovoitov wrote:
>> On 7/31/15 3:18 AM, Wangnan (F) wrote:
>>
>
> [SNIP]
>
>> didn't have time to look at it.
>> from your llvm patches looks like you've got quite experienced
>> with it already :)
>>
>>> I'll post 2 LLVM patches by replying this mail. Please have a look and
>>> help me
>>> send them to LLVM if you think my code is correct.
>>
>> patch 1:
>> I don't quite understand the purpose of builtin_dwarf_cfa
>> returning R11. It's a special register seen inside llvm codegen
>> only. It doesn't have kernel meaning.
>>
>
> Kernel side verifier allows us to do arithmetic computation using two 
> local variable
> address or local variable address and R11. Therefore, we can compute 
> the location
> of a local variable using:
>
>   mark = &my_var_a - __builtin_frame_address(0);
>
> If the stack allocation is fixed (if the location is never reused), 
> the above 'mark'
> can be uniquely identify a local variable. That's why I'm interesting 
> in it. However
> I'm not sure whether the prerequestion is hold.
>
>> patch 2:
>> do we really need to hack clang?
>> Can you just define a function that aliases to intrinsic,
>> like we do for ld_abs/ld_ind ?
>> void bpf_store_half(void *skb, u64 off, u64 val) 
>> asm("llvm.bpf.store.half");
>> then no extra patches necessary.
>>
>>> struct my_str {
>>>          int x;
>>>          int y;
>>> };
>>> struct my_str __str_my_str;
>>>
>>> struct my_str2 {
>>>          int x;
>>>          int y;
>>>          int z;
>>> };
>>> struct my_str2 __str_my_str2;
>>>
>>>          test_func(__builtin_bpf_typeid(&__str_my_str));
>>>          test_func(__builtin_bpf_typeid(&__str_my_str2));
>>>          mov     r1, 1
>>>          call    4660
>>>          mov     r1, 2
>>>          call    4660
>>
>> this part looks good. I think it's usable.
>>
>> > 1. llvm.eh_typeid_for can be used on global variables only. So for 
>> each
>> > output
>> >     structure we have to define a global varable.
>>
>> why? I think it should work with local pointers as well.
>>
>
> It is defined by LLVM, in lib/CodeGen/Analysis.cpp:
>
> /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded 
> in V.
> GlobalValue *llvm::ExtractTypeInfo(Value *V) {
>   ...
>   assert((GV || isa<ConstantPointerNull>(V)) &&
>          "TypeInfo must be a global variable or NULL");   <-- we can 
> use only constant pointers
>   return GV;
> }
>
> So from llvm::Intrinsic::eh_typeid_for we can get type of global 
> variables only.
>
> We may need a new intrinsic for that.
>
>
>> > 2. We still need to find a way to connect the fetchd typeid with DWARF
>> > info.
>> >     Inserting that ID into DWARF may workable?
>>
>> hmm, that id should be the same id we're seeing in dwarf, right?
>
> There's no 'typeid' field in dwarf originally. I'm still looking for a 
> way
> to inject this ID into dwarf infromation.
>
>> I think it's used in exception handling which is reusing some of
>> the dwarf stuff for this, so the must be a way to connect that id
>> to actual type info. Though last time I looked at EH was
>> during g++ hacking days. No idea how llvm does it exactly, but
>> I'm assuming the logic for rtti should be similar.
>>
>
> I'm not sure whether RTTI use dwarf to deduce type information. I 
> think not,
> because dwarf infos can be stripped out.
>

Hi Alexei,

Just found that llvm::Intrinsic::eh_typeid_for is function specific. ID 
of same type in
different functions may be different. Here is an example:

static int (*bpf_output_event)(unsigned long, void *buf, int size) =
         (void *) 0x1234;

struct my_str {
         int x;
         int y;
};
struct my_str __str_my_str;

struct my_str2 {
         int x;
         int y;
         int z;
};
struct my_str2 __str_my_str2;

int func(int *ctx)
{
         struct my_str var_a;
         struct my_str2 var_b;
         bpf_output_event(__builtin_bpf_typeid(&__str_my_str), &var_a, 
sizeof(var_a));
         bpf_output_event(__builtin_bpf_typeid(&__str_my_str2), &var_b, 
sizeof(var_b));
         return 0;
}

int func2(int *ctx)
{
         struct my_str var_a;
         struct my_str2 var_b;

         /* change order here */
         bpf_output_event(__builtin_bpf_typeid(&__str_my_str2), &var_b, 
sizeof(var_b));
         bpf_output_event(__builtin_bpf_typeid(&__str_my_str), &var_a, 
sizeof(var_a))
         return 0;
}

This program uses __builtin_bpf_typeid(llvm::Intrinsic::eh_typeid_for) 
in func and func2
for same two types but in different order. We expect same type get same ID.

Compiled with:

  $ clang -target bpf -S -O2 -c ./test_bpf_typeid.c

The result is:

           .text
         .globl  func
         .align  8
func:                                   # @func
# BB#0:                                 # %entry
         mov     r2, r10
         addi    r2, -8
         mov     r1, 1
         mov     r3, 8
         call    4660
         mov     r2, r10
         addi    r2, -24
         mov     r1, 2
         mov     r3, 12
         call    4660
         mov     r0, 0
         ret

         .globl  func2
         .align  8
func2:                                  # @func2
# BB#0:                                 # %entry
         mov     r2, r10
         addi    r2, -24
         mov     r1, 1                  <--- we want 2 here.
         mov     r3, 12
         call    4660
         mov     r2, r10
         addi    r2, -8
         mov     r1, 2                  <--- we want 1 here.
         mov     r3, 8
         call    4660
         mov     r0, 0
         ret

         .comm   __str_my_str,8,4        # @__str_my_str
         .comm   __str_my_str2,12,4      # @__str_my_str2


Conclusion: llvm::Intrinsic::eh_typeid_for is not on the right direction...

Thank you.

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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ