
Due to the increasing complexity of modern software and hardware systems, fully automated software engineering methods, particularly those that focus on a single abstraction level, are insufficient to prevent, identify, and handle performance problems, bugs, and security vulnerabilities. Addressing these issues often requires gathering information from and attuning to multiple abstraction levels, usually incorporating manual analysis or deep domain knowledge. Analysis that crosses abstraction boundaries is challenging, but software engineering techniques can benefit when analysis at one abstraction level is informed by analyses on others. I use code representations as the medium for this work. First, I investigate long-held assumptions about how lower-level code representations affect human comprehension in a human study. I then cross the boundary between binary and source, showing how decompiled code can be leveraged to facilitate the repair of bugs and vulnerabilities when source code is not available. The insights gained from this success with decompiled code allow us to improve automated program repair by using static code transformations to manipulate the input code representation. Finally, I develop methods for aligning source code elements with binary code, in the absence of compiler-embedded information or recompilation. Together, this thesis shows that analyses and tools designed for or informed by a software abstraction level can benefit understanding, tools, and analyses designed for others, and extend their utility beyond or improve their accuracy on their intended code representation.