Talk: What every programmer should know about malloc

At CPPCon 2019, Samy Al Bahra, Paul Khuong and Hannes Frederic Sowa collaborated on presenting the foundations of malloc and the tips that helped them improve performance in the real world. Abstract Memory allocators are a critical part of the run-time system for languages such as C++. Over the last few decades, the requirements for general-purpose memory allocation have become significantly more complex with different allocators evolving to handle different workloads varying by process age, concurrency, allocation patterns, object sizes, access patterns and more.
Read more →

Talk: Abusing your memory model for fun and profit

The most efficient concurrent C++ data structures used in the wild today usually achieve break-neck performance by either constraining their workload or constraining correctness to a particular memory model. At CPPCon 2019, Paul Khuong and Samy Al Bahra collaborated on a talk sharing success stories of workload specialization in real-world workloads over the last few years. Abstract The most efficient concurrent C++ data structures used in the wild today usually achieve break-neck performance by either constraining their workload or constraining correctness to a particular memory model.
Read more →

A Workflow for Memory Error Checking

Memory error detection technologies such as valgrind and address sanitizer are a critical part of the toolkit for programmers doing manual memory management. These tools allow you to detect memory access errors, memory management bugs, race conditions and more, in your programs. They are heavily used in companies developing high quality software such as Google, Facebook, Mozilla and more. A general problem with all these tools is that there is no easy way to aggregate their errors and action on them.
Read more →

Debug Information is Huge and What to do About It

Debug information is used by symbolic debuggers and the Backtrace platform to reconcile process executable state to the source-code form that is familiar to most software engineers. This information is responsible for mapping memory addresses and register values to function names, source code locations and describing variables. Some environments choose to omit debug information. Of the many reasons, the typically valid reasons are disk utilization and arguably, intellectual property protection.
Read more →

Compile Once Debug Twice: Picking a compiler for debuggability

Have you ever had an assert get triggered only to result in a useless core dump with missing variable information or an invalid callstack? Common factors that go into selecting a C or C++ compiler are: availability, correctness, compilation speed and application performance. A factor that is often neglected is debug information quality, which symbolic debuggers use to reconcile application executable state to the source-code form that is familiar to most software engineers.
Read more →

Building a Go Debugger

Earlier this year we published a post titled Implementing A Debugger: The Fundamentals. This post gave an overview of debuggers, what they do, and how they work. In today’s post, we build upon this knowledge and talk about our journey of extending Backtrace’s debugger to support Go. Intro If you have the time and haven’t read Implement A Debugger: The Fundemantals, we highly recommend you do so. This post builds upon terms and knowledge discussed there.
Read more →

Post-Mortem Analysis: Stale Pointer Detection

We’ve previously posted a few blogs covering memory management, memory bugs, and post-mortem memory analysis. Now, we are excited to add another memory debug tool to Backtrace’s offering: stale pointer analysis. In this post, I will explain how this analysis works, its strengths, and its limitations. Introduction Among many memory errors, stale pointer is one of the subtlest and most difficult to debug. It happens when a memory region is freed or reallocated but the old references, aka aliases, to the memory are not updated properly.
Read more →

ROP exploitation detection

ROP exploitation in Linux The exploitation techniques used in stack-smashing have evolved right alongside the security mitigations that were created to prevent them. At one point in time an attacker was able to craft an exploit which overwrites the saved return address so that it points into a stack location where the shellcode was injected. This technique has been foiled by various security mechanisms over the years, but it was primarily DEP (data execution prevention) that created the necessity for an exploit to return somewhere other than the stack.
Read more →

Post-Mortem Heap Analysis: TCMalloc

If you read our previous posts of Memory Management Bugs: An Introduction and Post-Mortem Memory Debugging, you have an idea how Backtrace may help debugging various memory errors. In this post, I will illustrate how it works under the hood with the example of TCMalloc, one of the memory allocators supported by Backtrace. TCMalloc Internals The primary goal of TCMalloc is high performance of memory allocations, especially for memory intensive applications in multi-threaded environment.
Read more →

Performance Improvements for FreeBSD kernel debugging

We previously explored FreeBSD userspace coredumps. Backtrace’s debugging platform supports FreeBSD kernel coredumps too, and their traces share many features. They are constructed somewhat differently, and in the process of adding support for them, we found a way to improve performance for automated programs accessing them. Read on to learn how information is extracted from a FreeBSD kernel core, and how we improved performance for this mechanism. Generating kernel core files A kernel core is typically only generated in exceptional circumstances.
Read more →