Re: [PATCH] EfficiencySanitizer implementation.

2018-10-08 Thread Denis Khalikov
I assume that the compiler based instrumentation,
should be more efficient than binary instrumentation.
But, I was just interested in the process of implementation
for that tool.
Sorry for the noise.

On 10/07/2018 11:03 AM, Richard Biener wrote:
> On October 6, 2018 10:17:48 PM GMT+02:00, Denis Khalikov 
>  wrote:
>> Hello everyone,
>> this is a patch which implements EfficiencySanitizer aka ESan
>> into GCC. The EfficiencySanitizer tool is available in the llvm.
>> So, the main idea was to port the runtime library into GCC and
>> implement GCC compiler pass on GIMPLE IR with the same semantics
>> as llvm does on llvm IR.
>> The main difference that this patch also enables ESan under 32 bit
>> ARM CPU with some changes to runtime library.
>> Link to the RFC on the llvm-dev:
>> https://lists.llvm.org/pipermail/llvm-dev/2016-April/098355.html
>>
>> I know this patch is not acceptable into GCC trunk, so, I send
>> this patch in the weekend to don't bother anyone, but may be
>> someone will be interested. Also, I'll be very appreciated for
>> any feedback.
>> GCC should be build with --enable-checking=release.
>>
>> This patch includes:
>>
>> 1. GCC pass for the CacheFragmentation tool on the GIMPLE IR.
>> Special compiler pass instruments every memory access into the struct
>> field with gimple internal call ESAN_RECORD_ACCESS and expands
>> it in sanopt pass.
>> Creates fields counter array, each cell of that array
>> counts memory accesses to the special field. Creates array of
>> the structs, where the every instance of the struct represents meta
>> info of the real struct.
>>
>> a. Source example:
>>
>> struct node {
>>   int a;
>>   int b;
>>   int c;
>> };
>>
>> int main () {
>>   struct node c;
>>   for (int i = 0; i < 100; ++i) {
>> c.a = i + 1;
>> c.b = i + 1;
>> c.c = i + 1;
>>   }
>>   return 0;
>> }
>>
>> b. Instrumented GIMPLE:
>>:
>>   _1 = i_4 + 1;
>>   .ESAN_RECORD_ACCESS (0B, 0);
>>   c.a = _1;
>>   _2 = i_4 + 1;
>>   .ESAN_RECORD_ACCESS (0B, 1);
>>   c.b = _2;
>>   _3 = i_4 + 1;
>>   .ESAN_RECORD_ACCESS (0B, 2);
>>   c.c = _3;
>>   i_11 = i_4 + 1;
>>
>> c. Assembler:
>>
>> # The fields counter array.
>> # Every cell 8 bytes long and represents the amount
>> # of the field accesses.
>>
>> .weakstruct.node$1$1$1
>> .bss
>> .align 8
>> .typestruct.node$1$1$1, @object
>> .sizestruct.node$1$1$1, 24
>> struct.node$1$1$1:
>> .zero24
>>
>> # Increment the specific cell by the field index.
>> # Actually __esan_increment, could be inlined.
>>movl$struct.node$1$1$1, %eax
>>movq%rax, %rdi
>>call__esan_increment
>>movl%ebx, -32(%rbp)
>>movl-20(%rbp), %eax
>>leal1(%rax), %ebx
>>movl$struct.node$1$1$1+8, %eax
>>movq%rax, %rdi
>>call__esan_increment
>>movl%ebx, -28(%rbp)
>>movl-20(%rbp), %eax
>>leal1(%rax), %ebx
>>movl$struct.node$1$1$1+16, %eax
>>movq%rax, %rdi
>>call__esan_increment
>>
>> # The array of the structs with
>> # meta info like size of the special struct,
>> # number of the fields and pointer to the
>> # fields counter array.
>>
>> .Lesan_info0:
>> .quad.LC0
>> .long12
>> .long3
>> .quad0
>> .quad0
>> .quad0
>> .quadstruct.node$1$1$1
>> .quad0
>>
>> __esan_init is inserted to the static constructor.
>> __esan_exit is inserted to the static destructor.
>>
>> d. Output:
>>
>> ==28719==  struct node
>> ==28719==   size = 12, count = 300, ratio = 2
>> ==28719==   # 0: count = 100
>> ==28719==   # 1: count = 100
>> ==28719==   # 2: count = 100
>> ==28719==EfficiencySanitizer: total struct field access count = 300
>>
>> 2. GCC pass for the WorkingSet tool.
>> Special compiler pass instruments every memory access in the program.
>> Memory accesses are simply prepended with a function call like
>> __esan_aligned_load(addr), __esan_aligned_store(addr).
>> Also, __esan_init is inserted to the static constructor and
>> __esan_exit is inserted to the static destructor.
>>
>> a. Assembler:
>>
>>   movq-32(%rbp), %rax
>>   movq%rax, %rdi
>>   call__esan_aligned_store1
>>
>&

Re: [PATCH] Frame pointer for arm with THUMB2 mode

2018-09-05 Thread Denis Khalikov

Richard,
thanks for the answer, got it.

On 09/05/2018 07:51 PM, Richard Earnshaw (lists) wrote:

On 05/09/18 17:43, Denis Khalikov wrote:

Thanks for the answers.

I understood that, this hack makes more mess in codegen for arm,
but can you please clarify what did you mean by


Only a single register can be used
as the frame chain.


As far as I understood, GCC for arm with THUMB2 mode uses r7 register as
frame pointer register by default (with -fno-omit-frame-pointer flag),
GCC for arm with ARM mode uses r11, so I didn't really propose
to change the frame pointer register.



On entry to a function the code has to save the existing frame register.
 It doesn't know (can't trivially know) whether the caller is code
compiled in Arm state or Thumb state.  So how can it save the caller's
frame register if they are not the same?

Furthermore, the 'other' frame register (ie r7 in Arm state, r11 in
Thumb) is available as a call-saved register, so can contain any random
value.  If you try to use that random value during a frame chain walk
your program will most like take an access violation.  It will certainly
give you a garbage frame chain.

R.


Thanks.

On 09/05/2018 06:32 PM, Wilco Dijkstra wrote:

Hi Denis,


Adding support for a frame chain would require an ABI change. It

would have to
 > work across GCC, LLVM, Arm, Thumb-1 and Thumb-2 - not a trivial
amount of
 > effort.



Clang already works that way.


No, that's incorrect like Richard pointed out. Only a single register
can be used
as the frame chain.


If we change the size of the traces to 2, it could be something like
this:

...

At the first example we lost the full context, from where the
control/data flow comes from.


If 2 is not sufficient, then try 3 or 4. It may also be feasible to
only enable
deeper unwinding for particular libraries so you only pay an extra
cost for
leaks you are interested in.


The stack layout like this enables only with compile time flag
(-mthumb-fp and works only together with -mthumb and
-fno-omit-frame-pointer). It does not affect other codegen.


But any code built like that will *always* run slower even if you
don't use
the sanitizer.

Wilco







Re: [PATCH] Frame pointer for arm with THUMB2 mode

2018-09-05 Thread Denis Khalikov

Thanks for the answers.

I understood that, this hack makes more mess in codegen for arm,
but can you please clarify what did you mean by

>Only a single register can be used
> as the frame chain.

As far as I understood, GCC for arm with THUMB2 mode uses r7 register as
frame pointer register by default (with -fno-omit-frame-pointer flag),
GCC for arm with ARM mode uses r11, so I didn't really propose
to change the frame pointer register.

Thanks.

On 09/05/2018 06:32 PM, Wilco Dijkstra wrote:

Hi Denis,


Adding support for a frame chain would require an ABI change. It

would have to
 > work across GCC, LLVM, Arm, Thumb-1 and Thumb-2 - not a trivial amount of
 > effort.



Clang already works that way.


No, that's incorrect like Richard pointed out. Only a single register can be 
used
as the frame chain.


If we change the size of the traces to 2, it could be something like this:

...

At the first example we lost the full context, from where the
control/data flow comes from.


If 2 is not sufficient, then try 3 or 4. It may also be feasible to only enable
deeper unwinding for particular libraries so you only pay an extra cost for
leaks you are interested in.


The stack layout like this enables only with compile time flag
(-mthumb-fp and works only together with -mthumb and
-fno-omit-frame-pointer). It does not affect other codegen.


But any code built like that will *always* run slower even if you don't use
the sanitizer.

Wilco



Re: [PATCH] Frame pointer for arm with THUMB2 mode

2018-09-05 Thread Denis Khalikov

Hi Wilco,
thanks for the answer.

> Adding support for a frame chain would require an ABI change. It 
would have to

> work across GCC, LLVM, Arm, Thumb-1 and Thumb-2 - not a trivial amount of
> effort.

Clang already works that way.
Please look at this commit:
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCallingConv.td?r1=269459=269458=269459

This is an example of code which clang generates
with -mthumb -fno-omit-frame-pointer -O2.

 @ %bb.0:
 push{r4, r5, r6, r7, lr}
 add r7, sp, #12
 push.w  {r8, r9, r10}
 sub sp, #56
 mov r8, r0
 movwr0, :lower16:_ZTVN6sensor14sensor_handlerE
 movtr0, :upper16:_ZTVN6sensor14sensor_handlerE
 mov r9, r8
 addsr0, #8
 str r0, [r9], #4

The only difference is clang sets frame pointer to the r7 on the stack 
instead gcc sets to lr,

but it already handles by the Sanitizers.

>
> So this sounds like the first thing to do is reducing the size of the 
stack traces.
> The default is 30 which is far larger than useful. Using 1 for 
example should
> always be fast (since you can use __builtin_return_address(0)) and 
still get
> the function that called malloc. Also if the unwinder happens to be 
too slow,

> it should be optimized and caching added etc.
>

If we change the size of the traces to 2, it could be something like this:

0xb42a50a0 is located 0 bytes inside of 88-byte region 
[0xb42a50a0,0xb42a50f8)

freed by thread T0 here:
#0 0xb6a35cc7 in __interceptor_free (/usr/lib/libasan.so+0x127cc7)
#1 0xb5fa64e3 in ipc::message::unref() 
(/lib/libsensord-shared.so+0xe4e3)


previously allocated by thread T0 here:
#0 0xb6a36157 in malloc (/usr/lib/libasan.so+0x128157)
#1 0xb2f8852d in accel_device::get_data(unsigned int, 
sensor_data_t**, int*) (/usr/lib/sensor/libsensor-hal-tm1.so+0x1052d)


Instead this:

0xb42250a0 is located 0 bytes inside of 88-byte region 
[0xb42250a0,0xb42250f8)

freed by thread T0 here:
#0 0xb6989cff in __interceptor_free (/usr/lib/libasan.so+0x127cff)
#1 0xb5fa64e3 in ipc::message::unref() 
(/lib/libsensord-shared.so+0xe4e3)
#2 0xb6efbf47 in sensor::sensor_handler::notify(char const*, 
sensor_data_t*, int) (/usr/bin/sensord+0x1ef47)
#3 0xb6efad43 in sensor::sensor_event_handler::handle(int, unsigned 
int) (/usr/bin/sensord+0x1dd43)

#4 0xb5fa3bbb  (/lib/libsensord-shared.so+0x)
#5 0xb62d9a15 in g_main_context_dispatch 
(/lib/libglib-2.0.so.0+0x91a15)

#6 0xb62da2d9  (/lib/libglib-2.0.so.0+0x922d9)
#7 0xb62da9a9 in g_main_loop_run (/lib/libglib-2.0.so.0+0x929a9)
#8 0xb5fa4e1b in ipc::event_loop::run(int) 
(/lib/libsensord-shared.so+0xce1b)

#9 0xb6eec9a5 in main (/usr/bin/sensord+0xf9a5)
#10 0xb5cb663b in __libc_start_main (/lib/libc.so.6+0x1663b)

previously allocated by thread T0 here:
#0 0xb698a18f in malloc (/usr/lib/libasan.so+0x12818f)
#1 0xb2f8852d in accel_device::get_data(unsigned int, 
sensor_data_t**, int*) (/usr/lib/sensor/libsensor-hal-tm1.so+0x1052d)
#2 0xb6ef848f in 
sensor::physical_sensor_handler::get_data(sensor_data_t**, int*) 
(/usr/bin/sensord+0x1b48f)
#3 0xb6efaa51 in sensor::sensor_event_handler::handle(int, unsigned 
int) (/usr/bin/sensord+0x1da51)

#4 0xb5fa3bbb  (/lib/libsensord-shared.so+0x)
#5 0xb62d9a15 in g_main_context_dispatch 
(/lib/libglib-2.0.so.0+0x91a15)

#6 0xb62da2d9  (/lib/libglib-2.0.so.0+0x922d9)
#7 0xb62da9a9 in g_main_loop_run (/lib/libglib-2.0.so.0+0x929a9)
#8 0xb5fa4e1b in ipc::event_loop::run(int) 
(/lib/libsensord-shared.so+0xce1b)

#9 0xb6eec9a5 in main (/usr/bin/sensord+0xf9a5)
#10 0xb5cb663b in __libc_start_main (/lib/libc.so.6+0x1663b)


At the first example we lost the full context, from where the 
control/data flow comes from.


>
> The issue is that the frame pointer and frame chain always add a large
> overhead even when you do not use any sanitizers. This is especially bad
> for the proposed patch - you lose much of the benefit of using Thumb-2...
>

The stack layout like this enables only with compile time flag 
(-mthumb-fp and works only together with -mthumb and

-fno-omit-frame-pointer). It does not affect other codegen.

Thanks.

On 09/05/2018 03:11 PM, Wilco Dijkstra wrote:

Hi Denis,


We are working on applying Address/LeakSanitizer for the full Tizen OS
distribution. It's about ~1000 packages, ASan/LSan runtime is installed
to ld.so.preload. As we know ASan/LSan has interceptors for
allocators/deallocators such as (malloc/realloc/calloc/free) and so on.
On every allocation from user space program, ASan calls
GET_STACK_TRACE_MALLOC;
which unwinds the stack frame, and by default uses frame based stack
unwinder. So, it requires to build with "-fno-omit-frame-pointer",
switching it to default unwinder really hits the performance in our case.


So this sounds like the first thing to do is reducing the size of the stack 
traces.
The default is 30 

Re: [PATCH] Frame pointer for arm with THUMB2 mode

2018-09-05 Thread Denis Khalikov

Hi Wilco,
thanks for the answer.

> Adding support for a frame chain would require an ABI change. It 
would have to

> work across GCC, LLVM, Arm, Thumb-1 and Thumb-2 - not a trivial amount of
> effort.

Clang already works that way.
Please look at this commit:
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCallingConv.td?r1=269459=269458=269459


This is an example of code which clang generates
with -mthumb -fno-omit-frame-pointer -O2.

 @ %bb.0:
 push{r4, r5, r6, r7, lr}
 add r7, sp, #12
 push.w  {r8, r9, r10}
 sub sp, #56
 mov r8, r0
 movwr0, :lower16:_ZTVN6sensor14sensor_handlerE
 movtr0, :upper16:_ZTVN6sensor14sensor_handlerE
 mov r9, r8
 addsr0, #8
 str r0, [r9], #4

The only difference is clang sets frame pointer to the r7 on the stack 
instead gcc sets to lr, but it already handles by the Sanitizers.


>
> So this sounds like the first thing to do is reducing the size of the 
stack traces.
> The default is 30 which is far larger than useful. Using 1 for 
example should
> always be fast (since you can use __builtin_return_address(0)) and 
still get
> the function that called malloc. Also if the unwinder happens to be 
too slow,

> it should be optimized and caching added etc.
>
If we change the size of the traces to 2, it could be something like this:

0xb42a50a0 is located 0 bytes inside of 88-byte region 
[0xb42a50a0,0xb42a50f8)

freed by thread T0 here:
#0 0xb6a35cc7 in __interceptor_free (/usr/lib/libasan.so+0x127cc7)
#1 0xb5fa64e3 in ipc::message::unref() 
(/lib/libsensord-shared.so+0xe4e3)


previously allocated by thread T0 here:
#0 0xb6a36157 in malloc (/usr/lib/libasan.so+0x128157)
#1 0xb2f8852d in accel_device::get_data(unsigned int, 
sensor_data_t**, int*) (/usr/lib/sensor/libsensor-hal-tm1.so+0x1052d)


Instead this:

0xb42250a0 is located 0 bytes inside of 88-byte region 
[0xb42250a0,0xb42250f8)

freed by thread T0 here:
#0 0xb6989cff in __interceptor_free (/usr/lib/libasan.so+0x127cff)
#1 0xb5fa64e3 in ipc::message::unref() 
(/lib/libsensord-shared.so+0xe4e3)
#2 0xb6efbf47 in sensor::sensor_handler::notify(char const*, 
sensor_data_t*, int) (/usr/bin/sensord+0x1ef47)
#3 0xb6efad43 in sensor::sensor_event_handler::handle(int, unsigned 
int) (/usr/bin/sensord+0x1dd43)

#4 0xb5fa3bbb  (/lib/libsensord-shared.so+0x)
#5 0xb62d9a15 in g_main_context_dispatch 
(/lib/libglib-2.0.so.0+0x91a15)

#6 0xb62da2d9  (/lib/libglib-2.0.so.0+0x922d9)
#7 0xb62da9a9 in g_main_loop_run (/lib/libglib-2.0.so.0+0x929a9)
#8 0xb5fa4e1b in ipc::event_loop::run(int) 
(/lib/libsensord-shared.so+0xce1b)

#9 0xb6eec9a5 in main (/usr/bin/sensord+0xf9a5)
#10 0xb5cb663b in __libc_start_main (/lib/libc.so.6+0x1663b)

previously allocated by thread T0 here:
#0 0xb698a18f in malloc (/usr/lib/libasan.so+0x12818f)
#1 0xb2f8852d in accel_device::get_data(unsigned int, 
sensor_data_t**, int*) (/usr/lib/sensor/libsensor-hal-tm1.so+0x1052d)
#2 0xb6ef848f in 
sensor::physical_sensor_handler::get_data(sensor_data_t**, int*) 
(/usr/bin/sensord+0x1b48f)
#3 0xb6efaa51 in sensor::sensor_event_handler::handle(int, unsigned 
int) (/usr/bin/sensord+0x1da51)

#4 0xb5fa3bbb  (/lib/libsensord-shared.so+0x)
#5 0xb62d9a15 in g_main_context_dispatch 
(/lib/libglib-2.0.so.0+0x91a15)

#6 0xb62da2d9  (/lib/libglib-2.0.so.0+0x922d9)
#7 0xb62da9a9 in g_main_loop_run (/lib/libglib-2.0.so.0+0x929a9)
#8 0xb5fa4e1b in ipc::event_loop::run(int) 
(/lib/libsensord-shared.so+0xce1b)

#9 0xb6eec9a5 in main (/usr/bin/sensord+0xf9a5)
#10 0xb5cb663b in __libc_start_main (/lib/libc.so.6+0x1663b)


At the first example we lost the full context, from where the 
control/data flow comes from.


>
> The issue is that the frame pointer and frame chain always add a large
> overhead even when you do not use any sanitizers. This is especially bad
> for the proposed patch - you lose much of the benefit of using Thumb-2...
>

The stack layout like this enables only with compile time flag 
(-mthumb-fp and works only together with -mthumb and

-fno-omit-frame-pointer). It does not affect other codegen.


Thanks.


On 09/05/2018 03:11 PM, Wilco Dijkstra wrote:

Hi Denis,


We are working on applying Address/LeakSanitizer for the full Tizen OS
distribution. It's about ~1000 packages, ASan/LSan runtime is installed
to ld.so.preload. As we know ASan/LSan has interceptors for
allocators/deallocators such as (malloc/realloc/calloc/free) and so on.
On every allocation from user space program, ASan calls
GET_STACK_TRACE_MALLOC;
which unwinds the stack frame, and by default uses frame based stack
unwinder. So, it requires to build with "-fno-omit-frame-pointer",
switching it to default unwinder really hits the performance in our case.


So this sounds like the first thing to do is reducing the size of the stack 
traces.
The default is 30 

[PING][PATCH] Frame pointer for arm with THUMB2 mode

2018-09-05 Thread Denis Khalikov
Hello everyone,
can someone, please, take a look on this patch
https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01656.html

Thanks.


Re: [PATCH] Frame pointer for arm with THUMB2 mode

2018-08-28 Thread Denis Khalikov

Hi,
thanks for the answer.

> Switching on the frame pointer typically costs 1-2% performance, so 
it's a bad
> idea to use it. However changing the frame pointer like in the 
proposed patch
> will have a much larger cost - both in performance and codesize. 
You'd be
> lucky if it is less than 10%. This is due to placing the frame 
pointer at the top
> rather than the bottom of the frame, and that is very inefficient in 
Thumb-2.

>
> You would need to unwind ~100k times a second before you might see a
> performance gain. However you pay the performance cost all the time, even
> when no unwinding is required. So I don't see this as being a good idea.
>
> If unwind performance is an issue, it would make far more sense to 
solve that.
> Profiling typically hits the same functions again and again. 
Callgraph profiling to
> a fixed depth hits the same functions all the time. So caching is the 
obvious

> solution.

We are working on applying Address/LeakSanitizer for the full Tizen OS
distribution. It's about ~1000 packages, ASan/LSan runtime is installed 
to ld.so.preload. As we know ASan/LSan has interceptors for 
allocators/deallocators such as (malloc/realloc/calloc/free) and so on.

On every allocation from user space program, ASan calls
GET_STACK_TRACE_MALLOC;
which unwinds the stack frame, and by default uses frame based stack
unwinder. So, it requires to build with "-fno-omit-frame-pointer", 
switching it to default unwinder really hits the performance in our case.


> Doing real unwinding is also far more accurate than frame pointer based
> unwinding (the latter doesn't handle leaf functions correctly, 
entry/exit in
> non-leaf functions and shrinkwrapped functions - and this breaks 
callgraph

> profiling).

I agree, but in our case, all interceptors for allocators are
leaf functions, so the frame based stack unwinder works well for us.

> So my question is, is there any point in making code run 
significantly slower

> all the time and in return get inaccurate unwinding?

By default we build packages with ("-marm" "-fno-omit-frame-pointer"),
because need frame based stack unwinder for every allocation, as I said
before. As we know GCC sets fp to lr on the stack with 
("-fno-omit-frame-pointer" and "-marm") and I don't really know why.
But the binary size is bigger than for thumb, so, we cannot use default 
thumb frame pointer and want to reduce binary size for the full 
sanitized image.


In other case clang works the same way, as I offered at the patch.
It has the same issue, but it was fixed at the end of 2017
https://bugs.llvm.org/show_bug.cgi?id=18505 (The topics starts from
discussion about APCS, but it is not the main point.)

Also, unresolved issue related to this
https://github.com/google/sanitizers/issues/640

Thanks.


On 08/28/2018 03:48 AM, Wilco Dijkstra wrote:

Hi,


But we still have an issue with performance, when we are using default
unwinder, which uses unwind tables. It could be up to 10 times faster to
use frame based stack unwinder instead "default unwinder".


Switching on the frame pointer typically costs 1-2% performance, so it's a bad
idea to use it. However changing the frame pointer like in the proposed patch
will have a much larger cost - both in performance and codesize. You'd be
lucky if it is less than 10%. This is due to placing the frame pointer at the 
top
rather than the bottom of the frame, and that is very inefficient in Thumb-2.

You would need to unwind ~100k times a second before you might see a
performance gain. However you pay the performance cost all the time, even
when no unwinding is required. So I don't see this as being a good idea.

If unwind performance is an issue, it would make far more sense to solve that.
Profiling typically hits the same functions again and again. Callgraph 
profiling to
a fixed depth hits the same functions all the time. So caching is the obvious
solution.

Doing real unwinding is also far more accurate than frame pointer based
unwinding (the latter doesn't handle leaf functions correctly, entry/exit in
non-leaf functions and shrinkwrapped functions - and this breaks callgraph
profiling).

So my question is, is there any point in making code run significantly slower
all the time and in return get inaccurate unwinding?

Cheers,
Wilco



[PATCH] Frame pointer for arm with THUMB2 mode

2018-08-27 Thread Denis Khalikov
Hello everyone,
I've created the patch which sets the frame pointer to the predictable 
location in the stack frame for arm with THUMB2 and non-leaf functions.

Issue:
At this moment GCC emits frame layout for arm with THUMB2 mode,
"-fno-omit-frame-pointer" and AAPCS, and does not set frame pointer to
predictable location at the function frame for non-leaf functions. And
this is right thing to do regarding to answer on my
question https://gcc.gnu.org/ml/gcc-help/2018-07/msg00093.html.
But we still have an issue with performance, when we are using default
unwinder, which uses unwind tables. It could be up to 10 times faster to 
use frame based stack unwinder instead "default unwinder". As we know, 
the frame based stack unwinder works good for arm with ARM32 mode 
("-marm" compile-time option), because fp points to the lr on the stack, 
but the binary size could be about 30%-40% larger than with THUMB2 mode 
("-mthumb" compile time option). So, I think it
could be good to have an ability to use frame based stack unwinder for
thumb mode too. In this case AddressSanitizer, which uses frame based
stack unwinder, by default for every allocation/deallocation, could
benefit too.

Unresolved issue related to AddressSanitizer/LeakSanitzer:
https://github.com/google/sanitizers/issues/640

Problems:
By default arm with THUMB2 mode uses r7 register as frame pointer
register and it could be hard to set frame pointer to the predictable
location in the frame for some functions and some level of optimization.
For example interceptor for malloc in libasan built with
("-mthumb -fno-omit-frame-pointer -O2"):

000aa118 <__interceptor_malloc>:
stmdb   sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
subwsp, sp, #1076
add r7, sp, #16
...
function body
...
addwr7, r7, #1060
mov sp, r7
ldmia.w sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}

r7 points to sp + 16 after allocating 1076 bytes on the stack and
it's impossible to find the lr at the runtime.

In other way registers should be pushed in ascending order and we cannot 
change function prologue to this:

   push {r4, r5, r6, r8, r9, sl, r11, r7, lr }

And seems to me, the right solution is to make multiple push and 
multiple pop in the same order (clang works that way):

   push {r4, r5, r6, r7, lr}
   push {r8, r9, sl, r11 }
   add r7, sp, #32
   subw sp, sp #1076
   ...
   function body
   ...
   subw r7, #32
   mov sp, r7
   pop {r8, r9, sl, r11 }
   pop {r4, r5, r6, r7, pc }

So the r7 points to lr on the stack after function prologue and we can
find previous frame pointer by

subw r7, r7, #4
ldr r7, [r7]

at the runtime.

Verification steps:
1. I've build full Tizen OS distribution which consists of about ~1000
packages with that patch "-mthumb -fno-omit-frame-pointer -mthumb-fp 
-O2" and AddressSanitizer.
2. I've built the image from those packages and verified it on real
device with armv7 ISA, and it seems works. Also stack based frame
unwinder works.
3. It's hard to write correct test case, because gcc pushes {r8... r11}
registers only on some level of optimization and the source file should
have some amount of function. So, it's kinda hard to find the small test 
case. I have many preprocessed files with size about ~1kk bytes.
4. The frame layout for malloc interceptor in libasan which was built
with that patch and ("-fno-omit-frame-poiniter -O2 -mthumb -mthumb-fp")
looks like this:

000bb1f4 <__interceptor_malloc>:
   push{r4, r5, r6, r7, lr}
   ldr r6, [pc, #340]  ; (bb34c <__interceptor_malloc+0x158>)
   ldr r3, [pc, #340]  ; (bb350 <__interceptor_malloc+0x15c>)
   add r6, pc
   stmdb   sp!, {r8, r9, sl, fp}
   add r7, sp, #32
   subwsp, sp, #1076   ; 0x434
   ...
   function body
   ...
   subsr7, #32
   mov sp, r7
   ldmia.w sp!, {r8, r9, sl, fp}
   pop {r4, r5, r6, r7, pc}

5. I've faced only one build fail related to this patch - glibc package,
but this is related to option name, some build machinery does not
recognize the "-mthumb-fp" option, and I'm not sure that glibc could be
build with frame layout like this.

It would be nice to get review for this patch by some experts. I could
miss a lot of corner cases.
Thanks.
From: Denis Khalikov 
Date: Thu, 23 Aug 2018 16:33:58 +0300
Subject: [PATCH] Frame pointer for arm with THUMB2 mode.

Set frame pointer to the predictable location in the stack frame
for arm with THUMB2 mode.

2018-08-23  Denis Khalikov  

  * config/arm/arm.c (arm_emit_multi_reg_pop_no_return): New function.
  (arm_compute_initial_elimination_offset): Add support for
  TARGET_THUMB_STACK_UNWIND.
  (arm_expand_prologue): Emit function prologue related to
  TARGET_THUMB_STACK_UNWIND.
  (thumb2_expand_return): Emit function epilogue related to
  TARGET_THUMB_STACK_UNWIND.
  (arm_expand_epilogue): Emit function epilogue related to
  TARGET_THUMB_STACK_UNWIND.
 

[PATCH][PR other/86198] Libacktrace and ".note.gnu.build-id" section.

2018-06-18 Thread Denis Khalikov
Hello,
this is a patch for PR other/86198
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86198
Thanks.
From: Denis Khalikov 
Date: Mon, 18 Jun 2018 20:46:39 +0300
Subject: [PATCH] PR other/86198

* elf.c (elf_add): Increase ".note.gnu.build-id" section size
checking up to 36 bytes.
---
 libbacktrace/ChangeLog | 6 ++
 libbacktrace/elf.c | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index c01c7d8..2cc31bf 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,9 @@
+2018-06-18 Denis Khalikov 
+
+	PR other/86198
+	* elf.c (elf_add): Increase ".note.gnu.build-id" section size
+	checking up to 36 bytes.
+
 2018-04-24  H.J. Lu  
 
 	* configure: Regenerated.
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 0fd5e6f..f4863f0 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -2868,7 +2868,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 	  if (note->type == NT_GNU_BUILD_ID
 	  && note->namesz == 4
 	  && strncmp (note->name, "GNU", 4) == 0
-	  && shdr->sh_size < 12 + ((note->namesz + 3) & ~ 3) + note->descsz)
+	  && shdr->sh_size <= 12 + ((note->namesz + 3) & ~ 3) + note->descsz)
 	{
 	  buildid_data = >name[0] + ((note->namesz + 3) & ~ 3);
 	  buildid_size = note->descsz;
-- 
1.9.1



[PATCH][PR sanitizer/86090] Add checks for lstat and readlink to sanitizer configure.

2018-06-08 Thread Denis Khalikov
Hello,
this is a patch for PR sanitizer/86090
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86090
Thanks.
From: Denis Khalikov 
Date: Fri, 8 Jun 2018 19:53:01 +0300
Subject: [PATCH] PR sanitizer/86090

* configure.ac: Check for lstat and readlink.
* configure, config.h.in: Rebuild.
---
 libsanitizer/ChangeLog| 6 ++
 libsanitizer/config.h.in  | 6 ++
 libsanitizer/configure| 2 +-
 libsanitizer/configure.ac | 2 +-
 4 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 43eb1de..4c669dd 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,9 @@
+2018-06-08  Denis Khalikov  
+
+PR sanitizer/86090
+* configure.ac: Check for lstat and readlink.
+* configure, config.h.in: Rebuild.
+
 2018-05-31  Matthias Klose  
 
 	PR sanitizer/86012
diff --git a/libsanitizer/config.h.in b/libsanitizer/config.h.in
index 7195840..f716c24 100644
--- a/libsanitizer/config.h.in
+++ b/libsanitizer/config.h.in
@@ -43,6 +43,12 @@
 /* Define to 1 if you have the  header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the `lstat' function. */
+#undef HAVE_LSTAT
+
+/* Define to 1 if you have the `readlink' function. */
+#undef HAVE_READLINK
+
 /* Define to 1 if you have the  header file. */
 #undef HAVE_RPC_XDR_H
 
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 4695bc7..5836450 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -15509,7 +15509,7 @@ fi
 
 
 # Check for functions needed.
-for ac_func in clock_getres clock_gettime clock_settime
+for ac_func in clock_getres clock_gettime clock_settime lstat readlink
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/libsanitizer/configure.ac b/libsanitizer/configure.ac
index 0d11afd..34ba09f 100644
--- a/libsanitizer/configure.ac
+++ b/libsanitizer/configure.ac
@@ -93,7 +93,7 @@ AM_CONDITIONAL(TSAN_SUPPORTED, [test "x$TSAN_SUPPORTED" = "xyes"])
 AM_CONDITIONAL(LSAN_SUPPORTED, [test "x$LSAN_SUPPORTED" = "xyes"])
 
 # Check for functions needed.
-AC_CHECK_FUNCS(clock_getres clock_gettime clock_settime)
+AC_CHECK_FUNCS(clock_getres clock_gettime clock_settime lstat readlink)
 
 # Common libraries that we need to link against for all sanitizer libs.
 link_sanitizer_common='-lpthread -lm'
-- 
1.9.1



Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-09-11 Thread Denis Khalikov

Thanks for answer.
I understood all points which you mentioned, but can't
find last one
> It seems to work
> out the file name a second time, even though the file name must
> already be known.

Can you please show me where I've missed that, if you have a time for that.

Anyway, your patch works for me.
Thanks.

On 09/11/2017 12:11 AM, Ian Lance Taylor wrote:

On Sat, Jul 29, 2017 at 1:42 PM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:


Hello Ian,
thanks for review.
I've updated the patch, can you please take a look.


Apologies again for the length of time it took to reply.  I've had a
hard time understanding the patch.  It's quite likely that I don't
understand how it works, but it seems to pass the same file descriptor
to process_elf_header twice.  It seems to look for debug files with
the buildid in places where they will not be found.  It seems to work
out the file name a second time, even though the file name must
already be known.  I eventually just wrote my own implementation.

Could you try this patch and see if it works for your cases?  The
patch is against current mainline.  Thanks.

Ian



[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-09-05 Thread Denis Khalikov

Hello,
this is a ping for that patch:
https://gcc.gnu.org/ml/gcc-patches/2017-07/msg01958.html

Thanks.


[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-08-21 Thread Denis Khalikov

Hello,
this is a ping for that patch:
https://gcc.gnu.org/ml/gcc-patches/2017-07/msg01958.html

Thanks.


[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-08-14 Thread Denis Khalikov

Hello,
this is a ping for that patch
https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00022.html

Thanks.


Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-07-29 Thread Denis Khalikov

On 06/29/2017 02:59 AM, Ian Lance Taylor wrote:

On Fri, Jun 16, 2017 at 8:39 AM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:

Hello everyone,

This is a patch for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77631

Can some one please review attached patch.


Sorry to take so long about this.  It's a lot to look at.




diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 096ceb6..4bd97f3 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog


It's best if you don't include the ChangeLog as part of the patch.
The patch never applies cleanly anyhow.  Just put the ChangeLog entry
in the e-mail or as a separate attachment.  Actually I guess you did
that part, just leave ChangeLog out of the patch.  Thanks.


+AC_CHECK_HEADERS(limits.h)
+
+AC_CHECK_HEADERS(sys/param.h)


May as well put these in a single AC_CHECK_HEADERS.  But actually it
looks like you only want these to determine PATH_MAX, and I don't
think it's worth it.  Just use 4096.


+  LINK = 1,
+  REGULAR = 2


These names, and also DYN, INVALID, and EXEC, are a little too short
and too likely to conflict with some sloppy system header file.  The
enums in this code all use a prefix for each element; do that here
too.


+/* Cast from void pointer to uint32_t.  */
+
+static uint32_t
+getl32 (void *p)
+{
+  char *addr = (char *) p;
+  uint32_t v = 0;
+  v = *((uint32_t *) addr);
+  return v;
+}


The comment here doesn't look right; this isn't a cast.  And the
argument should really be char*.  But more importantly, the name
suggests that you want a little-endian read, but this won't fetch a
little-endian value on a big-endian system.  Either do a proper
little-endian fetch byte by byte, as the DWARF code already does, or
clarify the function name.  I don't know what you actually need.


+/* Function that produce a crc32 value for input buffer.  */


Let's move the CRC32 stuff into a different file.  Add a comment
explaining how the table was generated.


+  static const unsigned long crc32_table[256]


Seems like this should be uint32_t.  In any case not `unsigned long`,
which is 64 bits.  In general the CRC code seems to use `unsigned
long` where I would expect `uint32_t`.


+  unsigned char buffer[8 * 1024];


This code is called from signal handlers and on threads; this array is
too long to put on the stack.  Instead of looping and calling read
like this, use backtrace_get_view.


+/* Get length of the path.  */
+
+static int
+pathlen (const char *buffer)


This function doesn't seem to get the length of the path, it seems to
get the length of the base name.


+  if (offset >= section_size)
+return 0;
+  crc32_debug_link = getl32 (debug_link + offset);


Seems like you should compare offset + 4 to section_size to avoid
running off the end.


+  error_callback (data, "executable file is not ELF", 0);


This and other error messages no longer seem correct, as this function
is now used for files other than the executable file.

It doesn't seem like elf_get_section_by_name should call
process_elf_header, it seems like that will do unnecessary extra work.
For that matter elf_get_section_by_name shouldn't read the section
headers and names each time, we should only do that once.


+static int
+backtrace_readlink


This function should return type_of_file, and the enum should have an
error value.

+  if (buffer[0] == '/')

Use IS_ABSOLUTE_PATH.


+  debug_descriptor
+= backtrace_open_debugfile (descriptor, filename, error_callback,
+ data, state);


If you're going to call this from fileline.c, then the function needs
to be defined in pecoff.c also.  But calling it in fileline.c doesn't
seem right; why doesn't backtrace_initialize call it?

Ian



Hello Ian,
thanks for review.
I've updated the patch, can you please take a look.
Thanks.
From cbecf0d858c50aa00e5445b93fdd968e0778d225 Mon Sep 17 00:00:00 2001
From: Denis Khalikov <d.khali...@partner.samsung.com>
Date: Sat, 29 Jul 2017 22:14:48 +0300
Subject: [PATCH] PR sanitizer/77631

* elf.c (enum type_of_file): New enum.
(enum type_of_elf): New enum.
(enum debug_path): New enum.
(get_uint32): New function.
(get_crc32): New function.
(base_name_len): New function.
(check_sum): New function. Verify sum.
(process_elf_header): New function. Process elf header.
(elf_get_section_by_name): New function. Get section by name.
(backtrace_readlink): New function. Get type of file from filename.
(resolve_realname): New function. Resolve real name if file is link.
(backtrace_resolve_realname): New function. Resolve real name for any
file type.
(search_for_debugfile): New function. Search for debug file in known
paths.
(open_debugfile_by_gnulink): New function. Open debug file with
gnulink.
(hex): New function. Convert to hex.
(get_build_id_name): New function. Generate build-id name.
(open_debugfile_by_build_id): New function. Open deb

[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-07-23 Thread Denis Khalikov

Hello,
this is a ping for that patch
https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00022.html

Thanks.


[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-07-09 Thread Denis Khalikov

Hello,
this is a ping for that patch
https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00022.html

Thanks.


Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-07-01 Thread Denis Khalikov

Hello Ian,
thanks for review, I've fixed issues and updated the patch.
Can you please take a look.

Thanks.

On 06/29/2017 02:59 AM, Ian Lance Taylor wrote:

On Fri, Jun 16, 2017 at 8:39 AM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:

Hello everyone,

This is a patch for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77631

Can some one please review attached patch.


Sorry to take so long about this.  It's a lot to look at.




diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 096ceb6..4bd97f3 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog


It's best if you don't include the ChangeLog as part of the patch.
The patch never applies cleanly anyhow.  Just put the ChangeLog entry
in the e-mail or as a separate attachment.  Actually I guess you did
that part, just leave ChangeLog out of the patch.  Thanks.


+AC_CHECK_HEADERS(limits.h)
+
+AC_CHECK_HEADERS(sys/param.h)


May as well put these in a single AC_CHECK_HEADERS.  But actually it
looks like you only want these to determine PATH_MAX, and I don't
think it's worth it.  Just use 4096.


+  LINK = 1,
+  REGULAR = 2


These names, and also DYN, INVALID, and EXEC, are a little too short
and too likely to conflict with some sloppy system header file.  The
enums in this code all use a prefix for each element; do that here
too.


+/* Cast from void pointer to uint32_t.  */
+
+static uint32_t
+getl32 (void *p)
+{
+  char *addr = (char *) p;
+  uint32_t v = 0;
+  v = *((uint32_t *) addr);
+  return v;
+}


The comment here doesn't look right; this isn't a cast.  And the
argument should really be char*.  But more importantly, the name
suggests that you want a little-endian read, but this won't fetch a
little-endian value on a big-endian system.  Either do a proper
little-endian fetch byte by byte, as the DWARF code already does, or
clarify the function name.  I don't know what you actually need.


+/* Function that produce a crc32 value for input buffer.  */


Let's move the CRC32 stuff into a different file.  Add a comment
explaining how the table was generated.


+  static const unsigned long crc32_table[256]


Seems like this should be uint32_t.  In any case not `unsigned long`,
which is 64 bits.  In general the CRC code seems to use `unsigned
long` where I would expect `uint32_t`.


+  unsigned char buffer[8 * 1024];


This code is called from signal handlers and on threads; this array is
too long to put on the stack.  Instead of looping and calling read
like this, use backtrace_get_view.


+/* Get length of the path.  */
+
+static int
+pathlen (const char *buffer)


This function doesn't seem to get the length of the path, it seems to
get the length of the base name.


+  if (offset >= section_size)
+return 0;
+  crc32_debug_link = getl32 (debug_link + offset);


Seems like you should compare offset + 4 to section_size to avoid
running off the end.


+  error_callback (data, "executable file is not ELF", 0);


This and other error messages no longer seem correct, as this function
is now used for files other than the executable file.

It doesn't seem like elf_get_section_by_name should call
process_elf_header, it seems like that will do unnecessary extra work.
For that matter elf_get_section_by_name shouldn't read the section
headers and names each time, we should only do that once.


+static int
+backtrace_readlink


This function should return type_of_file, and the enum should have an
error value.

+  if (buffer[0] == '/')

Use IS_ABSOLUTE_PATH.


+  debug_descriptor
+= backtrace_open_debugfile (descriptor, filename, error_callback,
+ data, state);


If you're going to call this from fileline.c, then the function needs
to be defined in pecoff.c also.  But calling it in fileline.c doesn't
seem right; why doesn't backtrace_initialize call it?

Ian



From 053f4fab56ed45dec17c1d4c66868678c817acf9 Mon Sep 17 00:00:00 2001
From: Denis Khalikov <d.khali...@partner.samsung.com>
Date: Sat, 1 Jul 2017 23:37:34 +0300
Subject: [PATCH] PR sanitizer/77631

* elf.c (enum type_of_file): New enum.
(enum type_of_elf): New enum.
(enum debug_path): New enum.
(get_uint32): New function.
(get_crc32): New function.
(base_name_len): New function.
(check_sum): New function. Verify sum.
(process_elf_header): New function. Process elf header.
(elf_get_section_by_name): New function. Get section by name.
(backtrace_readlink): New function. Get type of file from filename.
(resolve_realname): New function. Resolve real name if file is link.
(backtrace_resolve_realname): New function. Resolve real name for any
file type.
(search_for_debugfile): New function. Search for debug file in known
paths.
(open_debugfile_by_gnulink): New function. Open debug file with
gnulink.
(hex): New function. Convert to hex.
(get_build_id_name): New function. Generate build-id name.
(open_debugfile_by_build_id): New function. Open deb

[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-06-25 Thread Denis Khalikov

Hello everyone,
this is a ping for patch
https://gcc.gnu.org/ml/gcc-patches/2017-06/msg01209.html


Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-06-19 Thread Denis Khalikov

Hello Matthias,
thanks for review.

As far as I understood that build-id should look like this:

https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html

"For the “build ID” method, GDB looks in the .build-id subdirectory of 
each one of the global debug directories for a file named 
nn/.debug, where nn are the first 2 hex characters of the build 
ID bit string, and  are the rest of the bit string. (Real build 
ID strings are 32 or more hex characters, not 10.)"


I also check gdb internals, for PR binutils/20876, which you provided.


1926   build_id = get_build_id (abfd);
1927   if (build_id == NULL)
1928 return NULL;
1929
1930   /* Compute the debug pathname corresponding to the build-id.  */
1931   name = bfd_malloc (strlen (".build-id/") + build_id->size * 2 + 2 
+ strlen (".debug"));

1932   if (name == NULL)
1933 {
1934   bfd_set_error (bfd_error_no_memory);
1935   return NULL;
1936 }
1937   n = name;
1938   d = build_id->data;
1939   s = build_id->size;
1940
1941   n += sprintf (n, ".build-id/");
1942   n += sprintf (n, "%02x", (unsigned) *d++); s--;
1943   n += sprintf (n, "/");
1944   while (s--)
1945 n += sprintf (n, "%02x", (unsigned) *d++);
1946   n += sprintf (n, ".debug");
1947


In my patch I do the same, in case we can't use printf functions family, 
because we can't use malloc.


 972   debug_postfix = ".debug";
 973   debug_prefix = ".build-id/";
 ...
 990   memset (build_id_name, 0, *len);
 991   memcpy (build_id_name, debug_prefix, debug_prefix_len);
 992   temp = build_id_name + debug_prefix_len;
 993
 994   *temp++ = hex ((*hash_start & 0xF0) >> 4);
 995   *temp++ = hex (*hash_start & 0x0F);
 996   ++hash_start;
 997   --hash_size;
 998
 999   memcpy (temp, "/", 1);
1000   ++temp;
1001
1002   while (hash_size--)
1003 {
1004   *temp++ = hex ((*hash_start & 0xF0) >> 4);
1005   *temp++ = hex (*hash_start & 0x0F);
1006   ++hash_start;
1007 }

In this case if we have binary with build id:

0x0123456789abcdef0123456789abcdef01234567

For example we can use linker option to specify build-id manually:

-Wl,--build-id=0x0123456789abcdef0123456789abcdef01234567

I expect to find .build-id link to debug file at least at path

/usr/lib/debug/.build-id/01/23456789abcdef0123456789abcdef01234567.debug

May be I'am missing something ?

I also can provide 3 more tests for this patch, but it will
increase patch size in about 1,5 times.

Thanks.

On 06/18/2017 05:08 PM, Matthias Klose wrote:

On 16.06.2017 17:39, Denis Khalikov wrote:

Hello everyone,

This is a patch for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77631

Can some one please review attached patch.


not a full review, but it looks like the system debug files based on build-id's
are not found.  In newer distro releases you find these at

$ ls /usr/lib/debug/.build-id/
00/ 0d/ 1a/ 25/ 2e/ 3a/ 45/ 4d/ 57/ 64/ 6d/ 77/ 82/ 8b/ 94/ a0/ a9/ b7/ c1/ cd/
d6/ e0/ eb/ f6/
01/ 0e/ 1b/ 26/ 2f/ 3b/ 46/ 4e/ 58/ 65/ 6e/ 78/ 83/ 8c/ 95/ a1/ ac/ b9/ c4/ ce/
d7/ e1/ ec/ f7/
02/ 11/ 1c/ 27/ 30/ 3d/ 47/ 50/ 59/ 66/ 6f/ 79/ 84/ 8e/ 96/ a2/ ae/ ba/ c5/ d0/
d8/ e3/ ee/ f9/
03/ 15/ 1d/ 28/ 32/ 3e/ 48/ 51/ 5b/ 67/ 70/ 7a/ 85/ 8f/ 99/ a3/ b0/ bb/ c6/ d1/
d9/ e4/ ef/ fb/
05/ 16/ 1e/ 29/ 35/ 41/ 49/ 52/ 5c/ 68/ 72/ 7b/ 87/ 90/ 9a/ a4/ b1/ bc/ c8/ d2/
db/ e5/ f1/ fc/
08/ 17/ 1f/ 2a/ 36/ 42/ 4a/ 53/ 5e/ 69/ 73/ 7c/ 88/ 91/ 9b/ a5/ b2/ be/ c9/ d3/
dc/ e6/ f2/ fd/
09/ 18/ 20/ 2b/ 37/ 43/ 4b/ 54/ 60/ 6a/ 75/ 7f/ 89/ 92/ 9c/ a6/ b4/ bf/ cb/ d4/
dd/ e7/ f3/ fe/
0a/ 19/ 24/ 2d/ 39/ 44/ 4c/ 55/ 61/ 6b/ 76/ 80/ 8a/ 93/ 9f/ a7/ b5/ c0/ cc/ d5/
de/ e8/ f5/ ff/

the first two bytes of the crc make the sub dir name, the debug file name has
these first two bytes omitted.

$ ls /usr/lib/debug/.build-id/0d
c55467dc9eb81a00c7715a790844e7cf035345.debug

objdump/objcopy in binutils 2.28 has these lookups properly working.

Matthias





[PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-06-16 Thread Denis Khalikov

Hello everyone,

This is a patch for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77631

Can some one please review attached patch.

Thanks.
From ae74cf3d632b06a91a986e32e3a6c16223767b24 Mon Sep 17 00:00:00 2001
From: Denis Khalikov <d.khali...@partner.samsung.com>
Date: Fri, 16 Jun 2017 12:13:13 +0300
Subject: [PATCH] PR sanitizer/77631

	* Makefile.in: Regenerated.
	* configure.ac: Add searching for limits.h, sys/param.h
	* config.h.in: Regenerated.
	* configure: Regenerated.
	* elf.c (enum type_of_file): New enum.
	(enum type_of_elf): New enum.
	(enum debug_path): New enum.
	(getl32): New function.
	(gnu_debuglink_crc32): New function. Generate crc32 sum.
	(get_crc32): New function.
	(pathlen): New function.
	(check_sum): New function. Verify sum.
	(process_elf_header): New function. Verify elf header.
	(elf_get_section_by_name): New function. Get section by name.
	(backtrace_readlink): New function. Get type of file from filename.
	(resolve_realname): New function. Resolve real name if file is link.
	(backtrace_resolve_realname): New function. Resolve real name for any
	file type.
	(search_for_debugfile): New function. Search for debug file in known
	paths.
	(open_debugfile_by_gnulink): New function. Open debug file with
	gnulink.
	(hex): New function. Convert to hex.
	(get_build_id_name): New function. Generate build-id name.
	(open_debugfile_by_build_id): New function. Open debug file with
	build-id.
	(backtrace_open_debugfile): New function. Open debug file.
	(elf_add): Move code which reads elf header to elf_header_is_valid.
	(phdr_callback): Call backtrace_open_debugfile function for shared
	library.
	* fileline.c (fileline_initialize): Call backtrace_open_debugfile for
	executable.
	* internal.h: Updated.
---
 libbacktrace/ChangeLog|  37 ++
 libbacktrace/Makefile.in  |   2 +-
 libbacktrace/config.h.in  |   6 +
 libbacktrace/configure|  26 ++
 libbacktrace/configure.ac |   4 +
 libbacktrace/elf.c| 949 +-
 libbacktrace/fileline.c   |  13 +-
 libbacktrace/internal.h   |   8 +
 8 files changed, 958 insertions(+), 87 deletions(-)

diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 096ceb6..4bd97f3 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,40 @@
+2017-06-16  Denis Khalikov  <d.khali...@partner.samsung.com>
+
+	PR sanitizer/77631
+	* Makefile.in: Regenerated.
+	* configure.ac: Add searching for limits.h, sys/param.h
+	* config.h.in: Regenerated.
+	* configure: Regenerated.
+	* elf.c (enum type_of_file): New enum.
+	(enum type_of_elf): New enum.
+	(enum debug_path): New enum.
+	(getl32): New function.
+	(gnu_debuglink_crc32): New function. Generate crc32 sum.
+	(get_crc32): New function.
+	(pathlen): New function.
+	(check_sum): New function. Verify sum.
+	(process_elf_header): New function. Verify elf header.
+	(elf_get_section_by_name): New function. Get section by name.
+	(backtrace_readlink): New function. Get type of file from filename.
+	(resolve_realname): New function. Resolve real name if file is link.
+	(backtrace_resolve_realname): New function. Resolve real name for any
+	file type.
+	(search_for_debugfile): New function. Search for debug file in known
+	paths.
+	(open_debugfile_by_gnulink): New function. Open debug file with
+	gnulink.
+	(hex): New function. Convert to hex.
+	(get_build_id_name): New function. Generate build-id name.
+	(open_debugfile_by_build_id): New function. Open debug file with
+	build-id.
+	(backtrace_open_debugfile): New function. Open debug file.
+	(elf_add): Move code which reads elf header to elf_header_is_valid.
+	(phdr_callback): Call backtrace_open_debugfile function for shared
+	library.
+	* fileline.c (fileline_initialize): Call backtrace_open_debugfile for
+	executable.
+	* internal.h: Updated.
+
 2017-05-02  Release Manager
 
 	* GCC 7.1.0 released.
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index de74b5d..e604b6c 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -16,7 +16,7 @@
 @SET_MAKE@
 
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012-2016 Free Software Foundation, Inc.
+# Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in
index 87cb805..edbd9af 100644
--- a/libbacktrace/config.h.in
+++ b/libbacktrace/config.h.in
@@ -28,6 +28,9 @@
 /* Define to 1 if you have the  header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define 1 if  is available. */
+#undef HAVE_LIMITS_H
+
 /* Define to 1 if you have the  header file. */
 #undef HAVE_LINK_H
 
@@ -52,6 +55,9 @@
 /* Define to 1 if you have the  header file. */
 #undef HAVE_SYS_MMAN_H
 
+/* Define 1 if  is available. */
+#undef HAVE_SYS_PARAM_H
+
 /* Define to 1 if you have the  header file. */
 #undef HAVE_SYS_STAT_H

[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-05-25 Thread Denis Khalikov

Hello everyone,

this is a ping for that patch
https://gcc.gnu.org/ml/gcc-patches/2017-05/msg01462.html

Can someone please review that patch.
Thanks.


Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-05-18 Thread Denis Khalikov

Hello everyone,
i've updated the patch recently for this issue:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77631

Can someone please review it.

Thanks.


On 04/13/2017 01:07 AM, Jeff Law wrote:

Given this doesn't look like a regression, I'm going to punt to gcc-8.

jeff
From: Denis Khalikov <d.khali...@partner.samsung.com>
Date: Thu, 18 May 2017 16:04:17 +0300
Subject: [PATCH] 	PR sanitizer/77631

	* Makefile.am: Regenerated.
	* Makefile.in: Regenerated.
	* configure.ac: Add searching for limits.h and sys/param.h
	* config.h.in: Regenerated.
	* configure: Regenerated.
	* elf.c (enum type_of_file): New enum.
	* elf.c (enum_type_of_elf): New enum.
	(enum debug_path): New enum.
	(getl32): New function.
	(gnu_debuglink_crc32): New function. Generate crc32 sum.
	(get_crc32): New function.
	(pathlen): New function.
	(check_sum): New function. Verify sum.
	(process_elf_header): New function. Verify elf header.
	(elf_get_section_by_name): New function. Get section by name.
	(backtrace_readlink): New function. Get type of file from filename.
	(resolve_realname): New function. Resolve real name if file is link.
	(backtrace_resolve_realname): New function. Resolve real name for any
	file type.
	(search_for_debugfile): New function. Search for debug file in known
	paths.
	(open_debugfile_by_gnulink): New function. Open debug file with
	gnulink.
	(hex): New function. Convert to hex.
	(get_build_id_name): New function. Generate build-id name.
	(open_debugfile_by_build_id): New function. Open debug file with
	build-id.
	(backtrace_open_debugfile): New function. Open debug file.
	(elf_add): Move code which reads elf header to elf_header_is_valid.
	(phdr_callback): Call backtrace_open_debugfile function for shared
	library.
	* fileline.c (fileline_initialize): Call backtrace_open_debugfile for
	executable.
	* internal.h: Updated.
---
 libbacktrace/ChangeLog|  38 ++
 libbacktrace/Makefile.in  |   2 +-
 libbacktrace/config.h.in  |   6 +
 libbacktrace/configure|  18 +
 libbacktrace/configure.ac |   6 +
 libbacktrace/elf.c| 977 +-
 libbacktrace/fileline.c   |  11 +-
 libbacktrace/internal.h   |   5 +
 8 files changed, 971 insertions(+), 92 deletions(-)

diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 25cd921..33bbf63 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,41 @@
+2017-05-18  Denis Khalikov  <d.khali...@partner.samsung.com>
+
+	PR sanitizer/77631
+	* Makefile.am: Regenerated.
+	* Makefile.in: Regenerated.
+	* configure.ac: Add searching for limits.h and sys/param.h
+	* config.h.in: Regenerated.
+	* configure: Regenerated.
+	* elf.c (enum type_of_file): New enum.
+	* elf.c (enum_type_of_elf): New enum.
+	(enum debug_path): New enum.
+	(getl32): New function.
+	(gnu_debuglink_crc32): New function. Generate crc32 sum.
+	(get_crc32): New function.
+	(pathlen): New function.
+	(check_sum): New function. Verify sum.
+	(process_elf_header): New function. Verify elf header.
+	(elf_get_section_by_name): New function. Get section by name.
+	(backtrace_readlink): New function. Get type of file from filename.
+	(resolve_realname): New function. Resolve real name if file is link.
+	(backtrace_resolve_realname): New function. Resolve real name for any
+	file type.
+	(search_for_debugfile): New function. Search for debug file in known
+	paths.
+	(open_debugfile_by_gnulink): New function. Open debug file with
+	gnulink.
+	(hex): New function. Convert to hex.
+	(get_build_id_name): New function. Generate build-id name.
+	(open_debugfile_by_build_id): New function. Open debug file with
+	build-id.
+	(backtrace_open_debugfile): New function. Open debug file.
+	(elf_add): Move code which reads elf header to elf_header_is_valid.
+	(phdr_callback): Call backtrace_open_debugfile function for shared
+	library.
+	* fileline.c (fileline_initialize): Call backtrace_open_debugfile for
+	executable.
+	* internal.h: Updated.
+
 2017-03-08  Sam Thursfield  <sam.thursfi...@codethink.co.uk>
 
 	* btest.c (test5): Replace #ifdef guard with 'unused' attribute
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index de74b5d..e604b6c 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -16,7 +16,7 @@
 @SET_MAKE@
 
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012-2016 Free Software Foundation, Inc.
+# Copyright (C) 2012-2017 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in
index 87cb805..edbd9af 100644
--- a/libbacktrace/config.h.in
+++ b/libbacktrace/config.h.in
@@ -28,6 +28,9 @@
 /* Define to 1 if you have the  header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define 1 if  is available. */
+#undef HAVE_LIMITS_H
+
 /* Define to 1 if you have the  header file. */
 #undef HAVE_LINK_H
 
@@ -52,6 +55,9 

Re: [PATCH][PR sanitizer/80414] Fix segfault with -fsanitize=undefined on 32 bit host

2017-04-13 Thread Denis Khalikov

Thanks for review.

I updated the patch.


On 04/13/2017 04:10 PM, Jakub Jelinek wrote:

On Thu, Apr 13, 2017 at 12:28:40PM +0300, Denis Khalikov wrote:

--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-15.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+int main()
+{
+  long long offset = 10;
+  char array[10];
+  char c = array[offset];
+  return 0;
+}


I would expect you want to dg-output here the runtime diagnostics,
at least some part of it, to make it clear the testcase is UB and
to test whether the UB is detected.


diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index c01d633..936 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -672,7 +672,8 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)

   /* Pick up the arguments of the UBSAN_BOUNDS call.  */
   tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
-  tree index = gimple_call_arg (stmt, 1);
+  tree index, orig_index;
+  index = orig_index = gimple_call_arg (stmt, 1);
   tree orig_index_type = TREE_TYPE (index);


Instead of this I'd suggest:
   tree index = gimple_call_arg (stmt, 1);
-  tree orig_index_type = TREE_TYPE (index);
+  tree orig_index = index;


   tree bound = gimple_call_arg (stmt, 2);

@@ -708,9 +709,9 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
   tree fn = builtin_decl_explicit (bcode);
-  tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
-  true, NULL_TREE, true,
-  GSI_SAME_STMT);
+  tree val
+   = force_gimple_operand_gsi (gsi, ubsan_encode_value (orig_index), true,
+   NULL_TREE, true, GSI_SAME_STMT);
   g = gimple_build_call (fn, 2, data, val);
 }
   gimple_set_location (g, loc);


and replace orig_index_type use with TREE_TYPE (orig_index)

Jakub



commit 5267088b655febb8dd9b675e5da7263ada41ead4
Author: Denis Khalikov <d.khali...@partner.samsung.com>
Date:   Thu Apr 13 12:03:19 2017 +0300

PR sanitizer/80414
* ubsan.c (ubsan_expand_bounds_ifn): Fix wrong tree val generation
for 32 bit host.
* c-c++-common/ubsan/bounds-15.c: New test.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3154103..283dbd6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-04-13  Denis Khalikov <d.khali...@partner.samsung.com>
+
+	PR sanitizer/80414
+	* ubsan.c (ubsan_expand_bounds_ifn): Fix wrong tree val generation
+	for 32 bit host.
+
 2017-04-12  Jan Hubicka  <hubi...@ucw.cz>
 
 	PR lto/69953 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b1594f2..fe55233 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-04-13  Denis Khalikov  <d.khali...@partner.samsung.com>
+
+	PR sanitizer/80414
+	* c-c++-common/ubsan/bounds-15.c: New test.
+
 2017-04-12  Jakub Jelinek  <ja...@redhat.com>
 
 	PR tree-optimization/79390
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-15.c b/gcc/testsuite/c-c++-common/ubsan/bounds-15.c
new file mode 100644
index 000..d62f5d5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-15.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+int main()
+{
+  long long offset = 10;
+  char array[10];
+  char c = array[offset];
+  return 0;
+}
+
+/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'char \\\[10\\\]'" } */
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index c01d633..4159cc5 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -673,7 +673,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
   /* Pick up the arguments of the UBSAN_BOUNDS call.  */
   tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
   tree index = gimple_call_arg (stmt, 1);
-  tree orig_index_type = TREE_TYPE (index);
+  tree orig_index = index;
   tree bound = gimple_call_arg (stmt, 2);
 
   gimple_stmt_iterator gsi_orig = *gsi;
@@ -700,7 +700,7 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
   tree data
 	= ubsan_create_data ("__ubsan_out_of_bounds_data", 1, ,
 			 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
-			 ubsan_type_descriptor (orig_index_type),
+			 ubsan_type_descriptor (TREE_TYPE (orig_index)),
 			 NULL_TREE, NULL_TREE);
   data = build_fold_addr_expr_loc (loc, data);
   enum built_in_function bcode
@@ -708,9 +708,9 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
 	  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
   tree fn = builtin_decl_explicit (bcode);
-  tree val = force_gimple_operand_gsi (gsi, ubsa

[PATCH][PR sanitizer/80414] Fix segfault with -fsanitize=undefined on 32 bit host

2017-04-13 Thread Denis Khalikov

Hello everyone.

I have patch to fix segfault with -fsanitize=undefined on 32 bit host.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80414

Can someone please review it.

Thanks.






commit 3bb53510ae11a9fa1f79ae83469c2650abe81ab4
Author: Denis Khalikov <d.khali...@partner.samsung.com>
Date:   Thu Apr 13 12:03:19 2017 +0300

PR sanitizer/80414
* ubsan.c (ubsan_expand_bounds_ifn): Fix wrong tree val generation
for 32 bit host.
* c-c++-common/ubsan/bounds-15.c: New test.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3154103..283dbd6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-04-13  Denis Khalikov <d.khali...@partner.samsung.com>
+
+	PR sanitizer/80414
+	* ubsan.c (ubsan_expand_bounds_ifn): Fix wrong tree val generation
+	for 32 bit host.
+
 2017-04-12  Jan Hubicka  <hubi...@ucw.cz>
 
 	PR lto/69953 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b1594f2..fe55233 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-04-13  Denis Khalikov  <d.khali...@partner.samsung.com>
+
+	PR sanitizer/80414
+	* c-c++-common/ubsan/bounds-15.c: New test.
+
 2017-04-12  Jakub Jelinek  <ja...@redhat.com>
 
 	PR tree-optimization/79390
diff --git a/gcc/testsuite/c-c++-common/ubsan/bounds-15.c b/gcc/testsuite/c-c++-common/ubsan/bounds-15.c
new file mode 100644
index 000..2af709a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/bounds-15.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=bounds" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+int main()
+{
+  long long offset = 10;
+  char array[10];
+  char c = array[offset];
+  return 0;
+}
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index c01d633..936 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -672,7 +672,8 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
 
   /* Pick up the arguments of the UBSAN_BOUNDS call.  */
   tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
-  tree index = gimple_call_arg (stmt, 1);
+  tree index, orig_index;
+  index = orig_index = gimple_call_arg (stmt, 1);
   tree orig_index_type = TREE_TYPE (index);
   tree bound = gimple_call_arg (stmt, 2);
 
@@ -708,9 +709,9 @@ ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
 	  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
 	  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
   tree fn = builtin_decl_explicit (bcode);
-  tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
-	   true, NULL_TREE, true,
-	   GSI_SAME_STMT);
+  tree val
+	= force_gimple_operand_gsi (gsi, ubsan_encode_value (orig_index), true,
+NULL_TREE, true, GSI_SAME_STMT);
   g = gimple_build_call (fn, 2, data, val);
 }
   gimple_set_location (g, loc);


[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-04-10 Thread Denis Khalikov

Hello everyone,

this is a ping for

https://gcc.gnu.org/ml/gcc-patches/2017-03/msg01171.html


[PING][PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-03-29 Thread Denis Khalikov

Hello everyone,

can someone please review that patch
https://gcc.gnu.org/ml/gcc-patches/2017-03/msg01171.html

Thanks.


Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-03-22 Thread Denis Khalikov

Hello everyone,
I've fixed some issues and implemented functionality
to search debug file by build-id.
Can someone please review my patch.

> As far as I know all the debuglink code is ELF-specific.  I would do
> it all in elf.c.  While reading the sections of the executable, look
> for a debuglink section, and use it if present.  Keep the readlink
> code in posix.c, I suppose.  Apologies if this doesn't make sense.

I've moved backtrace_open_debugfile() function into elf.c.
This function checks debug sections (build-id/debuglink),
and if one of them exist - the function starts to search and open debug 
files.


Also I'll be very appreciated if someone give me advise about issues:
1.
| Skimming over the patch I noticed you duplicate libiberties xcrc32
| functionality.

To verify that debug file is valid, we should
verify crc32 sum, I took that algorithm from gdb, and
put it in the libbacktrace sources. However
this functionality is implemented by libiberty.
In case if libbactrace is being built as a static library,
I can't just link libbacktrace against static libbiberty.
Libtool can do it with objects which has "la" suffix,
but in time when libbacktrace build process happens
libiberty.la already removed.
Should i extract *.o files from the libiberty archive
and create libbacktrace archive with crc32.o from
libiberty or just keep this code in libbacktrace ?


2.
> > +clean_separate:glinktest.debug
> > + rm -f glinktest.debug
> > +
> > +separate: glinktest
> > + if test -n "$(OBJCOPY)" &&  test -n "$(STRIP)";  \
> > + then \
> > + $(OBJCOPY) --only-keep-debug glinktest glinktest.debug;\
> > + $(STRIP) glinktest;\
> > + $(OBJCOPY) --add-gnu-debuglink=glinktest.debug glinktest;\
> > + fi;
>
> |As far as I know "separate" is not a special thing in automake.  We
> | should always run (and clean) this test if the necessary objcopy
> | option is available.
>
In the attached patch I overrode default target check-TESTS
to use objcopy and strip, before test suite will run.
But the solution to move all test suite code from Makefile.in to 
Makefile.am seems not really good.
I searched for default target, which can be run before test suite logic, 
but can't find it for Makefile.am.

Should I keep current solution, or we have better alternative?

Thanks.


On 03/14/2017 04:49 PM, Ian Lance Taylor wrote:

On Mon, Mar 13, 2017 at 10:16 AM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:

Hello everyone, i have a patch for this issue.

List of implemented functionality:

1.Reading .gnu_debuglink section from ELF file:
 a. Reading name of debug info file.
 b. Verifying crc32 sum.

2. Searching for separate debug info file from paths:
 a. /usr/lib/debug/path/to/executable
 b. /path/to/executable
 c. /path/to/executable/.debug

Assumed that debug info file generated by objcopy from binutils.

objcopy --only-keep-debug foo foo.debug
strip -g foo
objcopy --add-gnu-debuglink=foo.debug foo



+clean_separate:glinktest.debug
+ rm -f glinktest.debug
+
+separate: glinktest
+ if test -n "$(OBJCOPY)" &&  test -n "$(STRIP)";  \
+ then \
+ $(OBJCOPY) --only-keep-debug glinktest glinktest.debug;\
+ $(STRIP) glinktest;\
+ $(OBJCOPY) --add-gnu-debuglink=glinktest.debug glinktest;\
+ fi;


As far as I know "separate" is not a special thing in automake.  We
should always run (and clean) this test if the necessary objcopy
option is available.


+glinktest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h


Missing '$'  in "$(INCDIR)".


+/* Return 1 if header is valid and -1 on fail */


This comment does not explain what the function actually does.


+/* Return the pointer to char array with data from .gnudebuglink section 
inside.  */


Line too long, we use 80 column lines.


+unsigned char *
+elf_gnu_debuglink_section (struct backtrace_state *state, int descriptor,
+   backtrace_error_callback error_callback, void *data,
+   int exe, int *gnulink_data_len_out)


This should be static.  I see that you are calling it elsewhere, but
it doesn't make sense to call an "elf" function outside of elf.c.
This library is used on non-ELF systems.


+  /* Look for for the .gnu_debuglink section  */


Period at end of sentence.


   /* To translate PC to file/line when using DWARF, we need to find
- the .debug_info and .debug_line sections.  */
+   the .debug_info and .debug_line sections.  */


Why change the indentation like this?  I think the original was correct.


-  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
-   pd->data, _not_exist);
+  descriptor
+ = backtrace_open_debugfile (info->dlpi_name, pd->error_callback, pd->data,
+_does_not_exist, pd->state, 0);
+  if (descriptor < 0)
+  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+   pd-

Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-03-14 Thread Denis Khalikov

Thanks for answer, i got it now.
I will also delete all readlink code. Looks like is no reason
to use it instead just one call of realpath(char*,char*). Binutils
using realpath in the same cases.

On 03/14/2017 07:26 PM, Ian Lance Taylor wrote:

On Tue, Mar 14, 2017 at 7:30 AM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:

Thanks for review, got all of my mistakes, except one.



-  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
-   pd->data, _not_exist);
+  descriptor
+ = backtrace_open_debugfile (info->dlpi_name, pd->error_callback,
pd->data,
+_does_not_exist, pd->state, 0);
+  if (descriptor < 0)
+  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+   pd->data, _not_exist);


This seems like unnecessary work.  Shouldn't we only try to open the
debug file if we find a .gnu_debuglink section?

Should i move code below

  /* check if debug section does exist */
 debug_link_data
= elf_gnu_debuglink_section (state, descriptor, error_callbackdata, exe,
_link_data_len);

from backtrace_open_debugfile .


As far as I know all the debuglink code is ELF-specific.  I would do
it all in elf.c.  While reading the sections of the executable, look
for a debuglink section, and use it if present.  Keep the readlink
code in posix.c, I suppose.  Apologies if this doesn't make sense.

Ian




On 03/14/2017 04:49 PM, Ian Lance Taylor wrote:


On Mon, Mar 13, 2017 at 10:16 AM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:


Hello everyone, i have a patch for this issue.

List of implemented functionality:

1.Reading .gnu_debuglink section from ELF file:
 a. Reading name of debug info file.
 b. Verifying crc32 sum.

2. Searching for separate debug info file from paths:
 a. /usr/lib/debug/path/to/executable
 b. /path/to/executable
 c. /path/to/executable/.debug

Assumed that debug info file generated by objcopy from binutils.

objcopy --only-keep-debug foo foo.debug
strip -g foo
objcopy --add-gnu-debuglink=foo.debug foo




+clean_separate:glinktest.debug
+ rm -f glinktest.debug
+
+separate: glinktest
+ if test -n "$(OBJCOPY)" &&  test -n "$(STRIP)";  \
+ then \
+ $(OBJCOPY) --only-keep-debug glinktest glinktest.debug;\
+ $(STRIP) glinktest;\
+ $(OBJCOPY) --add-gnu-debuglink=glinktest.debug glinktest;\
+ fi;



As far as I know "separate" is not a special thing in automake.  We
should always run (and clean) this test if the necessary objcopy
option is available.


+glinktest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h



Missing '$'  in "$(INCDIR)".


+/* Return 1 if header is valid and -1 on fail */



This comment does not explain what the function actually does.


+/* Return the pointer to char array with data from .gnudebuglink section
inside.  */



Line too long, we use 80 column lines.


+unsigned char *
+elf_gnu_debuglink_section (struct backtrace_state *state, int
descriptor,
+   backtrace_error_callback error_callback, void *data,
+   int exe, int *gnulink_data_len_out)



This should be static.  I see that you are calling it elsewhere, but
it doesn't make sense to call an "elf" function outside of elf.c.
This library is used on non-ELF systems.


+  /* Look for for the .gnu_debuglink section  */



Period at end of sentence.


   /* To translate PC to file/line when using DWARF, we need to find
- the .debug_info and .debug_line sections.  */
+   the .debug_info and .debug_line sections.  */



Why change the indentation like this?  I think the original was correct.


-  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
-   pd->data, _not_exist);
+  descriptor
+ = backtrace_open_debugfile (info->dlpi_name, pd->error_callback,
pd->data,
+_does_not_exist, pd->state, 0);
+  if (descriptor < 0)
+  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+   pd->data, _not_exist);



This seems like unnecessary work.  Shouldn't we only try to open the
debug file if we find a .gnu_debuglink section?


+/*Just a simple test copied from btest.c, but in this case we don't have
debug
+ * info in the executable and test should verify that we can read debug
info
+ * from separate file. See Makefile check-TESTS target. */



No leading '*' on subsequent lines of multi-line comments, see existing
code.

I'm not sure I see the point of glinktest.c.  Why don't we just use
btest.c?


+#define MAX_PATH_LEN 4096 /*  from linux/limits.h   */



This library works on systems other than GNU/Linux.  We should
dynamically allocate the buffer.


+  while (len > 1 && !IS_DIR_SEPARATOR (*(buffer + (len - 1



while (len > 1 && !IS_DIR_SEPARATOR(buffer[len-1]))

or just call basename.  I'm not sure why you bother with the count
variable; doesn't full_filename_len - count exactly == len?


+  sign_byte = 0x00;
+  count = 0;
+  while (*(buffer + count) != sign_byte && size > count)
+++count;
+  return count;



This looks like `return strnlen(buffer, size)`.

Ian











Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-03-14 Thread Denis Khalikov

Thanks for review, got all of my mistakes, except one.


> -  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
> -   pd->data, _not_exist);
> +  descriptor
> + = backtrace_open_debugfile (info->dlpi_name, pd->error_callback, 
pd->data,

> +_does_not_exist, pd->state, 0);
> +  if (descriptor < 0)
> +  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
> +   pd->data, _not_exist);

This seems like unnecessary work.  Shouldn't we only try to open the
debug file if we find a .gnu_debuglink section?

Should i move code below

  /* check if debug section does exist */
 debug_link_data
= elf_gnu_debuglink_section (state, descriptor, error_callbackdata, 
exe, _link_data_len);


from backtrace_open_debugfile .

On 03/14/2017 04:49 PM, Ian Lance Taylor wrote:

On Mon, Mar 13, 2017 at 10:16 AM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:

Hello everyone, i have a patch for this issue.

List of implemented functionality:

1.Reading .gnu_debuglink section from ELF file:
 a. Reading name of debug info file.
 b. Verifying crc32 sum.

2. Searching for separate debug info file from paths:
 a. /usr/lib/debug/path/to/executable
 b. /path/to/executable
 c. /path/to/executable/.debug

Assumed that debug info file generated by objcopy from binutils.

objcopy --only-keep-debug foo foo.debug
strip -g foo
objcopy --add-gnu-debuglink=foo.debug foo



+clean_separate:glinktest.debug
+ rm -f glinktest.debug
+
+separate: glinktest
+ if test -n "$(OBJCOPY)" &&  test -n "$(STRIP)";  \
+ then \
+ $(OBJCOPY) --only-keep-debug glinktest glinktest.debug;\
+ $(STRIP) glinktest;\
+ $(OBJCOPY) --add-gnu-debuglink=glinktest.debug glinktest;\
+ fi;


As far as I know "separate" is not a special thing in automake.  We
should always run (and clean) this test if the necessary objcopy
option is available.


+glinktest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h


Missing '$'  in "$(INCDIR)".


+/* Return 1 if header is valid and -1 on fail */


This comment does not explain what the function actually does.


+/* Return the pointer to char array with data from .gnudebuglink section 
inside.  */


Line too long, we use 80 column lines.


+unsigned char *
+elf_gnu_debuglink_section (struct backtrace_state *state, int descriptor,
+   backtrace_error_callback error_callback, void *data,
+   int exe, int *gnulink_data_len_out)


This should be static.  I see that you are calling it elsewhere, but
it doesn't make sense to call an "elf" function outside of elf.c.
This library is used on non-ELF systems.


+  /* Look for for the .gnu_debuglink section  */


Period at end of sentence.


   /* To translate PC to file/line when using DWARF, we need to find
- the .debug_info and .debug_line sections.  */
+   the .debug_info and .debug_line sections.  */


Why change the indentation like this?  I think the original was correct.


-  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
-   pd->data, _not_exist);
+  descriptor
+ = backtrace_open_debugfile (info->dlpi_name, pd->error_callback, pd->data,
+_does_not_exist, pd->state, 0);
+  if (descriptor < 0)
+  descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+   pd->data, _not_exist);


This seems like unnecessary work.  Shouldn't we only try to open the
debug file if we find a .gnu_debuglink section?


+/*Just a simple test copied from btest.c, but in this case we don't have debug
+ * info in the executable and test should verify that we can read debug info
+ * from separate file. See Makefile check-TESTS target. */


No leading '*' on subsequent lines of multi-line comments, see existing code.

I'm not sure I see the point of glinktest.c.  Why don't we just use btest.c?


+#define MAX_PATH_LEN 4096 /*  from linux/limits.h   */


This library works on systems other than GNU/Linux.  We should
dynamically allocate the buffer.


+  while (len > 1 && !IS_DIR_SEPARATOR (*(buffer + (len - 1


while (len > 1 && !IS_DIR_SEPARATOR(buffer[len-1]))

or just call basename.  I'm not sure why you bother with the count
variable; doesn't full_filename_len - count exactly == len?


+  sign_byte = 0x00;
+  count = 0;
+  while (*(buffer + count) != sign_byte && size > count)
+++count;
+  return count;


This looks like `return strnlen(buffer, size)`.

Ian





Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-03-14 Thread Denis Khalikov

Ok, thanks,
i will change patch to use crc32 from libiberty and
also implement searching for debuginfo with build id.
As it was implemented to binutils PR binutils/20876.

On 03/14/2017 04:21 PM, Ian Lance Taylor wrote:

On Tue, Mar 14, 2017 at 3:20 AM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:

Thanks for review,


Skimming over the patch I noticed you duplicate libiberties xcrc32
functionality.


should i take care about standalone libbacktrace ?
https://github.com/ianlancetaylor/libbacktrace


No, don't worry about it.

Ian





Re: [PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-03-14 Thread Denis Khalikov

Thanks for review,

> Skimming over the patch I noticed you duplicate libiberties xcrc32
> functionality.

should i take care about standalone libbacktrace ?
https://github.com/ianlancetaylor/libbacktrace

> Also the additions to posix.c probably belong to dwarf.c and elf.c 
(the feature

> is dwarf + elf specific but proper abstraction / #ifdefing should
> ensure compiling
> also succeeds for non-dwarf / non-elf platforms).

thanks, i will move code to elf.c since it's about reading section from 
elf format.



On 03/14/2017 11:27 AM, Richard Biener wrote:

On Mon, Mar 13, 2017 at 6:16 PM, Denis Khalikov
<d.khali...@partner.samsung.com> wrote:

Hello everyone, i have a patch for this issue.


Great!


List of implemented functionality:

1.Reading .gnu_debuglink section from ELF file:
 a. Reading name of debug info file.
 b. Verifying crc32 sum.

2. Searching for separate debug info file from paths:
 a. /usr/lib/debug/path/to/executable
 b. /path/to/executable
 c. /path/to/executable/.debug

Assumed that debug info file generated by objcopy from binutils.

objcopy --only-keep-debug foo foo.debug
strip -g foo
objcopy --add-gnu-debuglink=foo.debug foo


Skimming over the patch I noticed you duplicate libiberties xcrc32
functionality.

Also the additions to posix.c probably belong to dwarf.c and elf.c (the feature
is dwarf + elf specific but proper abstraction / #ifdefing should
ensure compiling
also succeeds for non-dwarf / non-elf platforms).

Leaving actual review to the maintainer (CCed).

Thanks,
Richard.





[PATCH][PR sanitizer/77631] Support separate debug info in libbacktrace

2017-03-13 Thread Denis Khalikov

Hello everyone, i have a patch for this issue.

List of implemented functionality:

1.Reading .gnu_debuglink section from ELF file:
 a. Reading name of debug info file.
 b. Verifying crc32 sum.

2. Searching for separate debug info file from paths:
 a. /usr/lib/debug/path/to/executable
 b. /path/to/executable
 c. /path/to/executable/.debug

Assumed that debug info file generated by objcopy from binutils.

objcopy --only-keep-debug foo foo.debug
strip -g foo
objcopy --add-gnu-debuglink=foo.debug foo

commit 6147ee1a9aeeb748563a8998033f2ce195460162
Author: Denis Khalikov <d.khali...@partner.samsung.com>
Date:   Mon Mar 13 18:55:36 2017 +0300

   PR sanitizer/77631
   * Makefile.am: Update to support glinktest.
   * Makefile.in: Regenerated.
   * configure.ac: Add AC_CHECK_PROG for objcopy.
   * configure: Regenerated.
   * elf.c (elf_header_is_valid): New function. Verify elf header.
   (elf_add): Move code which reads elf header to elf_header_is_valid.
   (elf_gnu_debuglink_section): New function. Read debuglink section from
elf.
   (phdr_callback): Call backtrace_open_debugfile function for shared
library.
   * fileline.c (fileline_initialize): Call backtrace_open_debugfile
function for executable.
   * glinktest.c: New test.
   * internal.h (MAX_PATH_LEN): Defined new variable.
   * posix.c (enum type_of_file): New enum.
   (enum debug_path): New enum.
   (getl32): New function.
   (gnu_debuglink_crc32): New function. Generate crc32 sum.
   (get_crc32): New function.
   (pathlen): New function.
   (check_sum): New function. Verify sum.
   (get_debug_filename_len): New function.
   (backtrace_readlink): New function.
   (backtrace_open_debugfile): New function.

diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 25cd921..cec5d3f 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,30 @@
+2017-03-13  Denis Khalikov  <d.khali...@partner.samsung.com>
+
+   PR sanitizer/77631
+   * Makefile.am: Update to support glinktest.
+   * Makefile.in: Regenerated.
+   * configure: Add script to find objcopy in the system.
+   * elf.c (elf_header_is_valid): New function. Verify elf header.
+   (elf_add): Move code which reads elf header to elf_header_is_valid.
+   (elf_gnu_debuglink_section): New function. Read debuglink section from
+elf.
+   (phdr_callback): Call backtrace_open_debugfile function for shared
+library.
+   * fileline.c (fileline_initialize): Call backtrace_open_debugfile
+function for executable.
+   * glinktest.c: New test.
+   * internal.h (MAX_PATH_LEN): Defined new variable.
+   * posix.c (enum type_of_file): New enum.
+   (enum debug_path): New enum.
+   (getl32): New function.
+   (gnu_debuglink_crc32): New function. Generate crc32 sum.
+   (get_crc32): New function.
+   (pathlen): New function.
+   (check_sum): New function. Verify sum.
+   (get_debug_filename_len): New function.
+   (backtrace_readlink): New function.
+   (backtrace_open_debugfile): New function.
+
 2017-03-08  Sam Thursfield  <sam.thursfi...@codethink.co.uk>
 
* btest.c (test5): Replace #ifdef guard with 'unused' attribute
diff --git a/libbacktrace/Makefile.am b/libbacktrace/Makefile.am
index 344dad5..17460a5 100644
--- a/libbacktrace/Makefile.am
+++ b/libbacktrace/Makefile.am
@@ -81,6 +81,17 @@ libbacktrace_la_LIBADD = \
 
 libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
 
+clean_separate:glinktest.debug
+   rm -f glinktest.debug
+
+separate: glinktest
+   if test -n "$(OBJCOPY)" &&  test -n "$(STRIP)";  \
+   then \
+   $(OBJCOPY) --only-keep-debug glinktest glinktest.debug;\
+   $(STRIP) glinktest;\
+   $(OBJCOPY) --add-gnu-debuglink=glinktest.debug glinktest;\
+   fi;
+
 # Testsuite.
 
 check_PROGRAMS =
@@ -100,6 +111,12 @@ stest_LDADD = libbacktrace.la
 
 check_PROGRAMS += stest
 
+glinktest_SOURCES = glinktest.c
+glinktest_CFLAGS = $(AM_CFLAGS) -g -O
+glinktest_LDADD = libbacktrace.la
+
+check_PROGRAMS += glinktest
+
 endif NATIVE
 
 # We can't use automake's automatic dependency tracking, because it
@@ -134,3 +151,4 @@ sort.lo: config.h backtrace.h internal.h
 stest.lo: config.h backtrace.h internal.h
 state.lo: config.h backtrace.h backtrace-supported.h internal.h
 unknown.lo: config.h backtrace.h internal.h
+glinktest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index de74b5d..354ecc7 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -84,7 +84,7 @@ build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
 check_PROGRAMS = $(am__EXEEXT_1)
-@NATIVE_TRUE@am__append_1 = btest stest
+@NATIVE_TRUE@am__append_1 = btest stest glinktest
 subdi