rk: remove unused PIE support

Change-Id: Ib7793724ef4e1c681898813e4ca5dd47a1960ae2
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
Tao Huang 2017-10-16 17:54:12 +08:00
commit 053de347cd
13 changed files with 0 additions and 1013 deletions

View file

@ -1,167 +0,0 @@
Position Independent Executables (PIEs)
=======================================
About
=====
The PIE framework is designed to allow normal C code from the kernel to be
embedded into the kernel, loaded at arbirary addresses, and executed.
A PIE is a position independent executable is a piece of self contained code
that can be relocated to any address. Before the code is run, a simple list
of offset based relocations has to be performed.
Copyright 2013 Texas Instruments, Inc
Russ Dill <russ.dill@ti.com>
Motivation
==========
Without the PIE framework, the only way to support platforms that require
code loaded to and run from arbitrary addresses was to write the code in
assembly. For example, a platform may have suspend/resume steps that
disable/enable SDRAM and must be run from on chip SRAM.
In addition to the SRAM virtual address not being known at compile time
for device tree platforms, the code must often run with the MMU enabled or
disabled (physical vs virtual address).
Design
======
The PIE code is separated into two main pieces. libpie satifies various
function calls emitted by gcc. The kernel contains only one copy of libpie
but whenever a PIE is loaded, a copy of libpie is copied along with the PIE
code. The second piece is the PIE code and data marked with special PIE
sections. At build time, libpie and the PIE sections are collected together
into a single PIE executable:
+---------------------------------------+
| __pie_common_start |
| <libpie> |
| __pie_common_end |
+---------------------------------------+
| __pie_overlay_start |
| +-----------------------------+ |
| | __pie_groupxyz_start | |
| | <groupxyz functions/data> | |
| | __pie_groupxyz_end | |
| +-----------------------------+ |
| | __pie_groupabc_start | |
| | <groupabc functions/data> | |
| | __pie_groupabc_end | |
| +-----------------------------+ |
| | __pie_groupijk_start | |
| | <groupijk functions/data> | |
| | __pie_groupijk_end | |
| +-----------------------------+ |
| __pie_overlay_end |
+---------------------------------------+
| <Architecture specific relocations> |
+---------------------------------------+
The PIE executable is then embedded into the kernel. Symbols are exported
from the PIE executable and passed back into the kernel at link time. When
the PIE is loaded, the memory layout then looks like the following:
+---------------------------------------+
| <libpie> |
+---------------------------------------+
| <groupabc_functions/data> |
+---------------------------------------+
| Tail (Arch specific data/relocations |
+---------------------------------------+
The architecture specific code is responsible for reading the relocations
and performing the necessary fixups.
Marking code/data
=================
Marking code and data for inclusing into a PIE group is done with the PIE
section markers, __pie(<group>) and __pie_data(<group>). Any symbols that
will be used outside of the PIE must be exported with EXPORT_PIE_SYMBOL:
static struct ddr_timings xyz_timings __pie_data(platformxyz) = {
[...]
};
void __pie(platformxyz) xyz_ddr_on(void *addr)
{
[...]
}
EXPORT_PIE_SYMBOL(xyz_ddr_on);
Loading PIEs
============
PIEs can be loaded into a genalloc pool (such as one backed by SRAM). The
following functions are provided:
- pie_load_sections(pool, <group>)
- pie_load_sections_phys(pool, <group>)
- pie_free(chunk)
pie_load_sections/pie_load_sections_phys load a PIE section group into the
given pool. Any necessary fixups are peformed and a chunk identifier is
returned. The first variant performs fixups such that the code can be run
with the current address layout. The second (phys) variant performs fixups
such that the code can be executed with the MMU disabled.
The pie_free function unloads a PIE from a pool.
Utilizing PIEs
==============
In order to translate between symbols and addresses within a loaded PIE, the
following macros/functions are provided:
- kern_to_pie(chunk, sym)
- fn_to_pie(chunk, fn)
- pie_to_phys(chunk, addr)
All three take as the first argument the chunk returned by pie_load_sections.
Data symbols can be translated with kern_to_pie. The macro is made so that
the type returned is the type passed:
kern_to_pie(chunk, xyz_struct_ptr)->foo = 15;
*kern_to_pie(chunk, &xyz_flags) = XYZ_DO_THE_THING;
Because certain architectures require special handling of function pointers,
a special varaint is provided:
ret = fn_to_pie(chunk, &xyz_ddr_on)(addr);
fnptr = fn_to_pie(chunk, &abc_fn);
In the case that a PIE has been configured to run with the MMU disabled,
physical addresses can be translated with pie_to_phys. For instance, if
the resume ROM jumps to a given physical address:
trampoline = fn_to_pie(chunk, resume_trampoline);
writel(pie_to_phys(chunk, trampoline), XYZ_RESUME_ADDR_REG);
On the Fly Fixup
================
The tail portion of the PIE can be used to store data necessary to perform
on the fly fixups. This is necessary for code that needs to run from
different address spaces at different times. Any on the fly fixup support
is architecture specific.
Architecture Requirements
=========================
Individual architectures must implement two functions:
pie_arch_fill_tail - This function examines the architecture specific
relocation entries and copies the ones necessary for the given PIE.
pie_arch_fixup - This function performs fixups of the PIE code based
on the tail data generated above.
pie.lds - A linker script for the PIE executable must be provided.
include/asm-generic/pie.lds.S provides a template.
libpie.o - The architecture must also provide a library of functions that
gcc may expect as a built-in, such as memcpy, memmove, etc. The list of
functions is architecture specific.

View file

@ -1,42 +0,0 @@
/*
* arch/arm/include/asm/pie.h
*
* Copyright 2013 Texas Instruments, Inc
* Russ Dill <russ.dill@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _ASMARM_PIE_H
#define _ASMARM_PIE_H
#include <linux/pie.h>
#ifdef CONFIG_PIE
extern void __pie_relocate(void);
extern void __pie___pie_relocate(void);
#define pie_relocate_from_pie() \
__asm__ __volatile__("bl __pie_relocate\n" \
: : : "cc", "memory", "lr", "r4", "r5", "r6", "r7", "r8", "r9");
static inline void pie_relocate_from_kern(struct pie_chunk *chunk)
{
void (*fn)(void) = fn_to_pie(chunk, &__pie___pie_relocate);
__asm__ __volatile__("" : : : "cc", "memory", "r4", "r5", "r6",
"r7", "r8", "r9");
fn();
}
#else
#define pie_relocate_from_pie() do {} while(0)
static inline void pie_relocate_from_kern(struct pie_chunk *chunk)
{
}
#endif
#endif

View file

@ -1,104 +0,0 @@
/*
* Copyright 2013 Texas Instruments, Inc.
* Russ Dill <russ.dill@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/pie.h>
#include <linux/elf.h>
#include <asm/elf.h>
#include <asm/pie.h>
extern char __pie_rel_dyn_start[];
extern char __pie_rel_dyn_end[];
extern char __pie_tail_offset[];
extern char __pie_reloc_offset[];
struct arm_pie_tail {
int count;
uintptr_t offset[0];
};
int pie_arch_fill_tail(void *tail, void *common_start, void *common_end,
void *overlay_start, void *code_start, void *code_end,
void *rel_start, void *rel_end)
{
Elf32_Rel *rel;
int records;
int i;
struct arm_pie_tail *pie_tail = tail;
int count;
void *kern_off;
rel = (Elf32_Rel *) __pie_rel_dyn_start;
records = (__pie_rel_dyn_end - __pie_rel_dyn_start) / sizeof(*rel);
count = 0;
for (i = 0; i < records; i++, rel++) {
if (ELF32_R_TYPE(rel->r_info) != R_ARM_RELATIVE)
break;
/* Adjust offset to match area in kernel */
kern_off = common_start + rel->r_offset;
if (kern_off >= common_start && kern_off < code_end) {
if (tail)
pie_tail->offset[count] = rel->r_offset;
count++;
}
}
rel = (Elf32_Rel *) rel_start;
records = (rel_end - rel_start) / sizeof(*rel);
for (i = 0; i < records; i++, rel++) {
if (ELF32_R_TYPE(rel->r_info) != R_ARM_RELATIVE)
break;
/* Adjust offset to match area in kernel */
kern_off = common_start + rel->r_offset;
if (kern_off >= common_start && kern_off < code_end) {
if (tail)
pie_tail->offset[count] = rel->r_offset;
count++;
}
}
if (tail)
pie_tail->count = count;
return count * sizeof(uintptr_t) + sizeof(*pie_tail);
}
EXPORT_SYMBOL_GPL(pie_arch_fill_tail);
/*
* R_ARM_RELATIVE: B(S) + A
* B(S) - Addressing origin of the output segment defining the symbol S.
* A - Addend for the relocation.
*/
int pie_arch_fixup(struct pie_chunk *chunk, void *base, void *tail,
unsigned long offset)
{
struct arm_pie_tail *pie_tail = tail;
void *reloc;
int i;
/* Perform relocation fixups for given offset */
for (i = 0; i < pie_tail->count; i++)
*((uintptr_t *) (pie_tail->offset[i] + base)) += offset;
/* Store the PIE offset to tail and recol func */
*kern_to_pie(chunk, (uintptr_t *) __pie_tail_offset) = tail - base;
reloc = kern_to_pie(chunk,
(void *) fnptr_to_addr(&__pie___pie_relocate));
*kern_to_pie(chunk, (uintptr_t *) __pie_reloc_offset) = reloc - base;
return 0;
}
EXPORT_SYMBOL_GPL(pie_arch_fixup);

View file

@ -1,46 +0,0 @@
/*
* ld script to make ARM PIEs
* taken from the ARM vmlinux.lds.S version by Russ Dill <russ.dill@ti.com.
*/
#include <asm-generic/pie.lds.h>
OUTPUT_ARCH(arm)
SECTIONS
{
. = 0x0;
PIE_COMMON_START
.got.plt : {
*(.got)
*(.got.plt)
}
.text : {
PIE_TEXT_TEXT
}
PIE_COMMON_END
__pie_rel_dyn_start : {
VMLINUX_SYMBOL(__pie_rel_dyn_start) = .;
}
.rel.dyn : {
KEEP(*(.rel.pie.text))
}
__pie_rel_dyn_end : {
VMLINUX_SYMBOL(__pie_rel_dyn_end) = .;
}
PIE_OVERLAY_START
OVERLAY : NOCROSSREFS {
PIE_OVERLAY_SECTION(overlay)
PIE_OVERLAY_SECTION(rk3288)
PIE_OVERLAY_SECTION(rk3188)
PIE_OVERLAY_SECTION(rk3036)
PIE_OVERLAY_SECTION(rk312x)
PIE_OVERLAY_SECTION(rk3126b)
}
PIE_OVERLAY_END
PIE_DISCARDS
}

View file

@ -1,3 +0,0 @@
lib1funcs.S
ashldi3.S
string.c

View file

@ -1,32 +0,0 @@
#
# linux/arch/arm/libpie/Makefile
#
ccflags-y := -fpic -mno-single-pic-base -fno-builtin
obj-y := relocate.o empty.o
obj-y += lib1funcs.o ashldi3.o string.o
# string library code (-Os is enforced to keep it much smaller)
string = $(obj)/string.o
CFLAGS_string.o := -Os
$(obj)/string.c: $(srctree)/arch/$(SRCARCH)/boot/compressed/string.c
$(call cmd,shipped)
# For __aeabi_uidivmod
lib1funcs = $(obj)/lib1funcs.o
$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
$(call cmd,shipped)
# For __aeabi_llsl
ashldi3 = $(obj)/ashldi3.o
$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S
$(call cmd,shipped)
$(obj)/libpie.o: $(string) $(lib1funcs) $(ashldi3) $(addprefix $(obj)/,$(OBJS))
$(call if_changed,ld)
# Make sure files are removed during clean
extra-y += string.c lib1funcs.S ashldi3.S

View file

@ -1,14 +0,0 @@
#include <linux/linkage.h>
ENTRY(__div0)
ENTRY(__gnu_mcount_nc)
ENTRY(__aeabi_unwind_cpp_pr0)
ENTRY(__aeabi_unwind_cpp_pr1)
ENTRY(__aeabi_unwind_cpp_pr2)
mov pc, lr
ENDPROC(__div0)
ENDPROC(__gnu_mcount_nc)
ENDPROC(__aeabi_unwind_cpp_pr0)
ENDPROC(__aeabi_unwind_cpp_pr1)
ENDPROC(__aeabi_unwind_cpp_pr2)

View file

@ -1,76 +0,0 @@
/*
* arch/arm/libpie/relocate.S - Relocation updating for PIEs
*
* Copyright 2013 Texas Instruments, Inc.
* Russ Dill <russ.dill@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <linux/linkage.h>
/*
* Update relocations based on current pc
*
* On exit:
* r4-r9 corrupted
*/
ENTRY(__pie_relocate)
/* Calculate offset of our code compared to existing relocations */
ldr r4, pie_relocate_address
adr r5, __pie_relocate
subs r6, r5, r4
moveq pc, lr /* 0 offset, no need to do anything */
/* Base of PIE group */
ldr r7, reloc_offset
sub r5, r5, r7
/* Calculate address of tail */
ldr r7, tail_offset
add r7, r7, r5
/* First byte of tail is number of entries */
ldr r8, [r7], #4
add r8, r7, r8, lsl #2
/*
* r5 - current base address of PIE group
* r6 - fixup offset needed for relocs
* r7 - relocs start
* r8 - relocs end
*/
1:
cmp r7, r8
ldrne r4, [r7], #4 /* Load next reloc offset */
addne r4, r4, r5 /* Calculate address of reloc entry */
ldrne r9, [r4]
addne r9, r9, r6 /* Fixup reloc entry */
strne r9, [r4]
bne 1b
mov pc, lr
ENDPROC(__pie_relocate)
/*
* This ends up in the .rel.dyn section and can be used to read the current
* relocation offset
*/
pie_relocate_address:
.long __pie_relocate
/* Offset from PIE section start to reloc function */
.global reloc_offset
reloc_offset:
.space 4
/* Offset from PIE section start to tail */
.globl tail_offset
tail_offset:
.space 4

View file

@ -1,90 +0,0 @@
/*
* Helper macros to support writing architecture specific
* pie linker scripts.
*
* A minimal linker scripts has following content:
* [This is a sample, architectures may have special requiriements]
*
* OUTPUT_FORMAT(...)
* OUTPUT_ARCH(...)
* SECTIONS
* {
* . = 0x0;
*
* PIE_COMMON_START
* .text {
* PIE_TEXT_TEXT
* }
* PIE_COMMON_END
*
* PIE_OVERLAY_START
* OVERLAY : NOCROSSREFS {
* PIE_OVERLAY_SECTION(am33xx)
* PIE_OVERLAY_SECTION(am347x)
* [...]
* }
* PIE_OVERLAY_END
*
* PIE_DISCARDS // must be the last
* }
*/
#include <asm-generic/vmlinux.lds.h>
#define PIE_COMMON_START \
__pie_common_start : { \
VMLINUX_SYMBOL(__pie_common_start) = .; \
}
#define PIE_COMMON_END \
__pie_common_end : { \
VMLINUX_SYMBOL(__pie_common_end) = .; \
}
#define PIE_OVERLAY_START \
__pie_overlay_start : { \
VMLINUX_SYMBOL(__pie_overlay_start) = .; \
}
#define PIE_OVERLAY_END \
__pie_overlay_end : { \
VMLINUX_SYMBOL(__pie_overlay_end) = .; \
}
#define PIE_TEXT_TEXT \
KEEP(*(.pie.text))
#define PIE_OVERLAY_SECTION(name) \
.pie.##name { \
KEEP(*(.pie.##name##.*)) \
VMLINUX_SYMBOL(__pie_##name##_start) = \
LOADADDR(.pie.##name##); \
VMLINUX_SYMBOL(__pie_##name##_end) = \
LOADADDR(.pie.##name##) + \
SIZEOF(.pie.##name##); \
} \
.rel.##name { \
KEEP(*(.rel.pie.##name##.*)) \
VMLINUX_SYMBOL(__pie_rel_##name##_start) = \
LOADADDR(.rel.##name##); \
VMLINUX_SYMBOL(__pie_rel_##name##_end) = \
LOADADDR(.rel.##name##) + \
SIZEOF(.rel.##name##); \
}
#define PIE_DISCARDS \
/DISCARD/ : { \
*(.dynsym) \
*(.dynstr*) \
*(.dynamic*) \
*(.plt*) \
*(.interp*) \
*(.gnu*) \
*(.hash) \
*(.comment) \
*(.bss*) \
*(.data) \
*(.discard) \
*(.discard.*) \
}

View file

@ -1,201 +0,0 @@
/*
* Copyright 2013 Texas Instruments, Inc.
* Russ Dill <russ.dill@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#ifndef _LINUX_PIE_H
#define _LINUX_PIE_H
#include <linux/kernel.h>
#include <linux/err.h>
#include <asm/fncpy.h>
#include <asm/bug.h>
struct gen_pool;
struct pie_chunk;
/**
* pie_arch_fixup - arch specific fixups of copied PIE code
* @chunk: identifier to be used with kern_to_pie/pie_to_phys
* @base: virtual address of start of copied PIE section
* @tail: virtual address of tail data in copied PIE
* @offset: offset to apply to relocation entries.
*
* When this code is done executing, it should be possible to jump to code
* so long as it is located at the given offset.
*/
extern int pie_arch_fixup(struct pie_chunk *chunk, void *base, void *tail,
unsigned long offset);
/**
* pie_arch_fill_tail - arch specific tail information for copied PIE
* @tail: virtual address of tail data in copied PIE to be filled
* @common_start: virtual address of common code within kernel data
* @common_end: virtual end address of common code within kernel data
* @overlay_start: virtual address of first overlay within kernel data
* @code_start: virtual address of this overlay within kernel data
* @code_end: virtual end address of this overlay within kernel data
*
* Fill tail data with data necessary to for pie_arch_fixup to perform
* relocations. If tail is NULL, do not update data, but still calculate
* the number of bytes required.
*
* Returns number of bytes required/used for tail on success, -EERROR otherwise.
*/
extern int pie_arch_fill_tail(void *tail, void *common_start, void *common_end,
void *overlay_start, void *code_start, void *code_end,
void *rel_start, void *rel_end);
#ifdef CONFIG_PIE
/**
* __pie_load_data - load and fixup PIE code from kernel data
* @pool: pool to allocate memory from and copy code into
* @start: virtual start address in kernel of chunk specific code
* @end: virtual end address in kernel of chunk specific code
* @phys: %true to fixup to physical address of destination, %false to
* fixup to virtual address of destination
*
* Returns 0 on success, -EERROR otherwise
*/
extern struct pie_chunk *__pie_load_data(struct gen_pool *pool, bool phys,
void *start, void *end,
void *rel_start, void *rel_end);
/**
* pie_to_phys - translate a virtual PIE address into a physical one
* @chunk: identifier returned by pie_load_sections
* @addr: virtual address within pie chunk
*
* Returns physical address on success, -1 otherwise
*/
extern phys_addr_t pie_to_phys(struct pie_chunk *chunk, unsigned long addr);
extern void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr);
/**
* pie_free - free the pool space used by an pie chunk
* @chunk: identifier returned by pie_load_sections
*/
extern void pie_free(struct pie_chunk *chunk);
#define __pie_load_sections(pool, name, phys) ({ \
extern char __pie_##name##_start[]; \
extern char __pie_##name##_end[]; \
extern char __pie_rel_##name##_start[]; \
extern char __pie_rel_##name##_end[]; \
\
__pie_load_data(pool, phys, \
__pie_##name##_start, __pie_##name##_end, \
__pie_rel_##name##_start, __pie_rel_##name##_end); \
})
/*
* Required for any symbol within an PIE section that is referenced by the
* kernel
*/
#define EXPORT_PIE_SYMBOL(sym) extern typeof(sym) sym __weak
/* For marking data and functions that should be part of a PIE */
#define __pie(name) __attribute__ ((__section__(".pie." #name ".text")))
#define __pie_data(name) __attribute__ ((__section__(".pie." #name ".data")))
#else
static inline struct pie_chunk *__pie_load_data(struct gen_pool *pool,
void *start, void *end, bool phys)
{
return ERR_PTR(-EINVAL);
}
static inline phys_addr_t pie_to_phys(struct pie_chunk *chunk,
unsigned long addr)
{
return -1;
}
static inline void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr)
{
return NULL;
}
static inline void pie_free(struct pie_chunk *chunk)
{
}
#define __pie_load_sections(pool, name, phys) ({ ERR_PTR(-EINVAL); })
#define EXPORT_PIE_SYMBOL(sym)
#define __pie(name)
#define __pie_data(name)
#endif
/**
* pie_load_sections - load and fixup sections associated with the given name
* @pool: pool to allocate memory from and copy code into
* fixup to virtual address of destination
* @name: the name given to __pie() and __pie_data() when marking
* data and code
*
* Returns 0 on success, -EERROR otherwise
*/
#define pie_load_sections(pool, name) ({ \
__pie_load_sections(pool, name, false); \
})
/**
* pie_load_sections_phys - load and fixup sections associated with the given
* name for execution with the MMU off
*
* @pool: pool to allocate memory from and copy code into
* fixup to virtual address of destination
* @name: the name given to __pie() and __pie_data() when marking
* data and code
*
* Returns 0 on success, -EERROR otherwise
*/
#define pie_load_sections_phys(pool, name) ({ \
__pie_load_sections(pool, name, true); \
})
/**
* kern_to_pie - convert a kernel symbol to the virtual address of where
* that symbol is loaded into the given PIE chunk.
*
* @chunk: identifier returned by pie_load_sections
* @p: symbol to convert
*
* Return type is the same as type passed
*/
#define kern_to_pie(chunk, p) ({ \
void *__ptr = (void *) (p); \
typeof(p) __result = (typeof(p)) __kern_to_pie(chunk, __ptr); \
__result; \
})
/**
* kern_to_fn - convert a kernel function symbol to the virtual address of where
* that symbol is loaded into the given PIE chunk
*
* @chunk: identifier returned by pie_load_sections
* @p: function to convert
*
* Return type is the same as type passed
*/
#define fn_to_pie(chunk, funcp) ({ \
uintptr_t __kern_addr, __pie_addr; \
\
__kern_addr = fnptr_to_addr(funcp); \
__pie_addr = kern_to_pie(chunk, __kern_addr); \
\
fnptr_translate(funcp, __pie_addr); \
})
#endif

142
lib/pie.c
View file

@ -1,142 +0,0 @@
/*
* Copyright 2013 Texas Instruments, Inc.
* Russ Dill <russ.dill@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/genalloc.h>
#include <linux/pie.h>
#include <asm/cacheflush.h>
struct pie_chunk {
struct gen_pool *pool;
unsigned long addr;
size_t sz;
};
extern char __pie_common_start[];
extern char __pie_common_end[];
extern char __pie_overlay_start[];
int __weak pie_arch_fill_tail(void *tail, void *common_start, void *common_end,
void *overlay_start, void *code_start, void *code_end,
void *rel_start, void *rel_end)
{
return 0;
}
int __weak pie_arch_fixup(struct pie_chunk *chunk, void *base, void *tail,
unsigned long offset)
{
return 0;
}
struct pie_chunk *__pie_load_data(struct gen_pool *pool, bool phys,
void *code_start, void *code_end,
void *rel_start, void *rel_end)
{
struct pie_chunk *chunk;
unsigned long offset;
int ret;
char *tail;
size_t common_sz;
size_t code_sz;
size_t tail_sz;
/* Calculate the tail size */
ret = pie_arch_fill_tail(NULL, __pie_common_start, __pie_common_end,
__pie_overlay_start, code_start, code_end,
rel_start, rel_end);
if (ret < 0)
goto err;
tail_sz = ret;
chunk = kzalloc(sizeof(*chunk), GFP_KERNEL);
if (!chunk) {
ret = -ENOMEM;
goto err;
}
common_sz = __pie_overlay_start - __pie_common_start;
code_sz = code_end - code_start;
chunk->pool = pool;
chunk->sz = common_sz + code_sz + tail_sz;
chunk->addr = gen_pool_alloc(pool, chunk->sz);
if (!chunk->addr) {
ret = -ENOMEM;
goto err_free;
}
/* Copy common code/data */
tail = (char *) chunk->addr;
memcpy(tail, __pie_common_start, common_sz);
tail += common_sz;
/* Copy chunk specific code/data */
memcpy(tail, code_start, code_sz);
tail += code_sz;
/* Fill in tail data */
ret = pie_arch_fill_tail(tail, __pie_common_start, __pie_common_end,
__pie_overlay_start, code_start, code_end,
rel_start, rel_end);
if (ret < 0)
goto err_alloc;
/* Calculate initial offset */
if (phys)
offset = gen_pool_virt_to_phys(pool, chunk->addr);
else
offset = chunk->addr;
/* Perform arch specific code fixups */
ret = pie_arch_fixup(chunk, (void *) chunk->addr, tail, offset);
if (ret < 0)
goto err_alloc;
flush_icache_range(chunk->addr, chunk->addr + chunk->sz);
return chunk;
err_alloc:
gen_pool_free(chunk->pool, chunk->addr, chunk->sz);
err_free:
kfree(chunk);
err:
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(__pie_load_data);
phys_addr_t pie_to_phys(struct pie_chunk *chunk, unsigned long addr)
{
return gen_pool_virt_to_phys(chunk->pool, addr);
}
EXPORT_SYMBOL_GPL(pie_to_phys);
void __iomem *__kern_to_pie(struct pie_chunk *chunk, void *ptr)
{
uintptr_t offset = (uintptr_t) ptr;
offset -= (uintptr_t) __pie_common_start;
if (offset >= chunk->sz)
return NULL;
else
return (void *) (chunk->addr + offset);
}
EXPORT_SYMBOL_GPL(__kern_to_pie);
void pie_free(struct pie_chunk *chunk)
{
gen_pool_free(chunk->pool, chunk->addr, chunk->sz);
kfree(chunk);
}
EXPORT_SYMBOL_GPL(pie_free);

3
pie/.gitignore vendored
View file

@ -1,3 +0,0 @@
*.syms
pie.lds
pie.lds.S

View file

@ -1,93 +0,0 @@
#
# linux/pie/Makefile
#
# Copyright 2013 Texas Instruments, Inc.
# Russ Dill <russ.dill@ti.com>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
obj-y := pie.bin.o
# Report unresolved symbol references
ldflags-y += --no-undefined
# Delete all temporary local symbols
ldflags-y += -X
# Reset objcopy flags, ARM puts "-O binary" here
OBJCOPYFLAGS =
# Reference gcc builtins for use in PIE with __pie_
$(obj)/pie_rename.syms: $(KBUILD_LIBPIE)
@$(NM) $^ | awk '{if ($$3) print $$3,"__pie_"$$3}' > $@
# For weakening the links to the original gcc builtins
$(obj)/pie_weaken.syms: $(KBUILD_LIBPIE)
@$(NM) $^ | awk '{if ($$3) print "__pie_"$$3}' > $@
# For embedding address of the symbols copied from the PIE into the kernel
$(obj)/pie.syms: $(obj)/pie.elf
@$(NM) $^ | awk '{if ($$3 && $$2 == toupper($$2)) print $$3,"=","0x"$$1" + _binary_pie_pie_bin_start;"}' > $@
# Collect together the libpie objects
LDFLAGS_libpie_stage1.o += -r
$(obj)/libpie_stage1.o: $(KBUILD_LIBPIE)
$(call if_changed,ld)
# Rename the libpie gcc builtins with a __pie_ prefix
OBJCOPYFLAGS_libpie_stage2.o += --redefine-syms=$(obj)/pie_rename.syms
OBJCOPYFLAGS_libpie_stage2.o += --rename-section .text=.pie.text
$(obj)/libpie_stage2.o: $(obj)/libpie_stage1.o $(obj)/pie_rename.syms
$(call if_changed,objcopy)
# Generate a version of vmlinux.o with weakened and rename references to gcc
# builtins.
OBJCOPYFLAGS_pie_stage1.o += --weaken-symbols=$(obj)/pie_weaken.syms
OBJCOPYFLAGS_pie_stage1.o += --redefine-syms=$(obj)/pie_rename.syms
$(obj)/pie_stage1.o: $(obj)/../vmlinux.o $(obj)/pie_rename.syms $(obj)/pie_weaken.syms
$(call if_changed,objcopy)
# Drop in the PIE versions instead
LDFLAGS_pie_stage2.o += -r
# Allow the _GLOBAL_OFFSET_TABLE to redefine
LDFLAGS_pie_stage2.o += --defsym=_GLOBAL_OFFSET_TABLE_=_GLOBAL_OFFSET_TABLE_
$(obj)/pie_stage2.o: $(obj)/pie_stage1.o $(obj)/libpie_stage2.o
$(call if_changed,ld)
# Drop everything but the pie sections
OBJCOPYFLAGS_pie_stage3.o += -j ".pie.*"
OBJCOPYFLAGS_pie_stage3.o += -j ".pie.text"
OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk3036.text" -j ".pie.rk3036.data"
OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk312x.text" -j ".pie.rk312x.data"
OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk3126b.text" -j ".pie.rk3126b.data"
OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk3188.text" -j ".pie.rk3188.data"
OBJCOPYFLAGS_pie_stage3.o += -j ".pie.rk3288.text" -j ".pie.rk3288.data"
$(obj)/pie_stage3.o: $(obj)/pie_stage2.o
$(call if_changed,objcopy)
# Create the position independant executable
LDFLAGS_pie.elf += -T $(KBUILD_PIE_LDS) --pie --gc-sections
$(obj)/pie.elf: $(obj)/pie_stage3.o $(KBUILD_PIE_LDS)
$(call if_changed,ld)
# Create binary data for the kernel
OBJCOPYFLAGS_pie.bin += -O binary
$(obj)/pie.bin: $(obj)/pie.elf $(obj)/pie.syms
$(call if_changed,objcopy)
# Import the data into the kernel
OBJCOPYFLAGS_pie.bin.o += -B $(ARCH) -I binary -O $(OBJCOPY_OUTPUT_FORMAT)
$(obj)/pie.bin.o: $(obj)/pie.bin
$(call if_changed,objcopy)
extra-y += pie_rename.syms pie_weaken.syms pie.syms pie.elf pie.bin