Code-Reuse attacks such as return-oriented programming constitute a powerful exploitation technique that is frequently leveraged to compromise software on a wide range of architectures. These attacks generate malicious computation based on existing code (so-called gadgets) residing in linked libraries. Both academia and industry have recently proposed defense techniques to mitigate code-reuse attacks. However, a continuous arms race has evolved between attacks and defenses. In this talk, we will elaborate on the evolution of code-reuse attacks. In particular, we explore prominent defense techniques that are based on control-flow integrity (CFI) enforcement and code randomization. Further, we discuss promising research directions such as hardware-assisted defenses and protection against these attacks at the kernel layer.