Commit ea3bc13f authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] More support for upward growing stacks

 - remove elf_caddr_t. It's positively dangerous to #define this since
   elf_caddr_t foo, bar; creates variables of different types (foo is
   char *, bar is char).
 - rewrite large chunks of create_elf_tables(), it needed cleaning anyway.
 - add upwards-growing stack support to create_elf_tables.
 - redefine the ARCH_DLINFO stuff on powerpc -- it's tested, works.
 - add upwards-growing-stack support to exec.c too.
parent b4093e0c
......@@ -54,7 +54,6 @@ static struct linux_binfmt irix_format = {
#ifndef elf_addr_t
#define elf_addr_t unsigned long
#define elf_caddr_t char *
#endif
#ifdef DEBUG_ELF
......@@ -155,8 +154,8 @@ unsigned long * create_irix_tables(char * p, int argc, int envc,
unsigned int interp_load_addr,
struct pt_regs *regs, struct elf_phdr *ephdr)
{
elf_caddr_t *argv;
elf_caddr_t *envp;
elf_addr_t *argv;
elf_addr_t *envp;
elf_addr_t *sp, *csp;
#ifdef DEBUG_ELF
......@@ -202,20 +201,20 @@ unsigned long * create_irix_tables(char * p, int argc, int envc,
#undef NEW_AUX_ENT
sp -= envc+1;
envp = (elf_caddr_t *) sp;
envp = sp;
sp -= argc+1;
argv = (elf_caddr_t *) sp;
argv = sp;
__put_user((elf_addr_t)argc,--sp);
current->mm->arg_start = (unsigned long) p;
while (argc-->0) {
__put_user((elf_caddr_t)(unsigned long)p,argv++);
__put_user((unsigned long)p,argv++);
p += strlen_user(p);
}
__put_user(NULL, argv);
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
while (envc-->0) {
__put_user((elf_caddr_t)(unsigned long)p,envp++);
__put_user((unsigned long)p,envp++);
p += strlen_user(p);
}
__put_user(NULL, envp);
......
......@@ -80,7 +80,6 @@ struct elf_prpsinfo32
};
#define elf_addr_t u32
#define elf_caddr_t u32
#define init_elf_binfmt init_elf32_binfmt
#undef CONFIG_BINFMT_ELF
#ifdef CONFIG_BINFMT_ELF32
......
......@@ -166,7 +166,6 @@ struct elf_prpsinfo32
#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
#define elf_addr_t u32
#define elf_caddr_t u32
/*
#define init_elf_binfmt init_elf32_binfmt
*/
......
......@@ -147,7 +147,6 @@ jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value)
}
#define elf_addr_t u32
#define elf_caddr_t u32
#undef start_thread
#define start_thread start_thread32
#define init_elf_binfmt init_elf32_binfmt
......
......@@ -186,7 +186,6 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen");
#undef MODULE_AUTHOR
#define elf_addr_t __u32
#define elf_caddr_t __u32
static void elf32_init(struct pt_regs *);
......
......@@ -39,19 +39,15 @@
#include <asm/param.h>
#include <asm/pgalloc.h>
#define DLINFO_ITEMS 13
#include <linux/elf.h>
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
static int load_elf_library(struct file*);
static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
extern void dump_thread(struct pt_regs *, struct user *);
#ifndef elf_addr_t
#define elf_addr_t unsigned long
#define elf_caddr_t char *
#endif
/*
......@@ -88,9 +84,9 @@ static void set_brk(unsigned long start, unsigned long end)
{
start = ELF_PAGEALIGN(start);
end = ELF_PAGEALIGN(end);
if (end <= start)
return;
if (end > start)
do_brk(start, end - start);
current->mm->start_brk = current->mm->brk = end;
}
......@@ -111,134 +107,149 @@ static void padzero(unsigned long elf_bss)
}
}
static elf_addr_t *
create_elf_tables(char *p, int argc, int envc,
struct elfhdr * exec,
unsigned long load_addr,
unsigned long load_bias,
unsigned long interp_load_addr, int ibcs)
/* Let's use some macros to make this stack manipulation a litle clearer */
#ifdef ARCH_STACK_GROWSUP
#define STACK_ADD(sp, items) ((elf_addr_t *)(sp) + (items))
#define STACK_ROUND(sp, items) \
((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
#define STACK_ALLOC(sp, len) ({ elf_addr_t old_sp = sp; sp += len; old_sp; })
#else
#define STACK_ADD(sp, items) ((elf_addr_t *)(sp) - (items))
#define STACK_ROUND(sp, items) \
(((unsigned long) (sp - items)) &~ 15UL)
#define STACK_ALLOC(sp, len) sp -= len
#endif
static void
create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
int interp_aout, unsigned long load_addr,
unsigned long interp_load_addr)
{
elf_caddr_t *argv;
elf_caddr_t *envp;
elf_addr_t *sp, *csp;
char *k_platform, *u_platform;
long hwcap;
size_t platform_len = 0;
size_t len;
unsigned long p = bprm->p;
int argc = bprm->argc;
int envc = bprm->envc;
elf_addr_t *argv, *envp;
elf_addr_t *sp, u_platform;
const char *k_platform = ELF_PLATFORM;
int items;
elf_addr_t elf_info[30];
int ei_index = 0;
/*
* Get hold of platform and hardware capabilities masks for
* the machine we are running on. In some cases (Sparc),
* this info is impossible to get, in others (i386) it is
* If this architecture has a platform capability string, copy it
* to userspace. In some cases (Sparc), this info is impossible
* for userspace to get any other way, in others (i386) it is
* merely difficult.
*/
hwcap = ELF_HWCAP;
k_platform = ELF_PLATFORM;
if (k_platform) {
platform_len = strlen(k_platform) + 1;
u_platform = p - platform_len;
__copy_to_user(u_platform, k_platform, platform_len);
} else
u_platform = p;
size_t len = strlen(k_platform) + 1;
#if defined(__i386__) && defined(CONFIG_SMP)
/*
* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
* by the processes running on the same package. One thing we can do
* is to shuffle the initial stack for them.
* In some cases (e.g. Hyper-Threading), we want to avoid L1
* evictions by the processes running on the same package. One
* thing we can do is to shuffle the initial stack for them.
*
* The conditionals here are unneeded, but kept in to make the
* code behaviour the same as pre change unless we have hyperthreaded
* processors. This should be cleaned up before 2.6
* code behaviour the same as pre change unless we have
* hyperthreaded processors. This should be cleaned up
* before 2.6
*/
if(smp_num_siblings > 1)
u_platform = u_platform - ((current->pid % 64) << 7);
if (smp_num_siblings > 1)
STACK_ALLOC(p, ((current->pid % 64) << 7));
#endif
u_platform = STACK_ALLOC(p, len);
__copy_to_user((void *)u_platform, k_platform, len);
}
/*
* Force 16 byte _final_ alignment here for generality.
*/
sp = (elf_addr_t *)(~15UL & (unsigned long)(u_platform));
csp = sp;
csp -= (1+DLINFO_ITEMS)*2 + (k_platform ? 2 : 0);
#ifdef DLINFO_ARCH_ITEMS
csp -= DLINFO_ARCH_ITEMS*2;
#endif
csp -= envc+1;
csp -= argc+1;
csp -= (!ibcs ? 3 : 1); /* argc itself */
if ((unsigned long)csp & 15UL)
sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
/*
* Put the ELF interpreter info on the stack
*/
#define NEW_AUX_ENT(nr, id, val) \
__put_user ((id), sp+(nr*2)); \
__put_user ((val), sp+(nr*2+1)); \
/* Create the ELF interpreter info */
#define NEW_AUX_ENT(id, val) \
do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0)
sp -= 2;
NEW_AUX_ENT(0, AT_NULL, 0);
if (k_platform) {
sp -= 2;
NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
}
sp -= DLINFO_ITEMS*2;
NEW_AUX_ENT( 0, AT_HWCAP, hwcap);
NEW_AUX_ENT( 1, AT_PAGESZ, ELF_EXEC_PAGESIZE);
NEW_AUX_ENT( 2, AT_CLKTCK, CLOCKS_PER_SEC);
NEW_AUX_ENT( 3, AT_PHDR, load_addr + exec->e_phoff);
NEW_AUX_ENT( 4, AT_PHENT, sizeof (struct elf_phdr));
NEW_AUX_ENT( 5, AT_PHNUM, exec->e_phnum);
NEW_AUX_ENT( 6, AT_BASE, interp_load_addr);
NEW_AUX_ENT( 7, AT_FLAGS, 0);
NEW_AUX_ENT( 8, AT_ENTRY, load_bias + exec->e_entry);
NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid);
NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
#ifdef ARCH_DLINFO
/*
* ARCH_DLINFO must come last so platform specific code can enforce
* special alignment requirements on the AUXV if necessary (eg. PPC).
* ARCH_DLINFO must come first so PPC can do its special alignment of
* AUXV.
*/
ARCH_DLINFO;
#endif
NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff);
NEW_AUX_ENT(AT_PHENT, sizeof (struct elf_phdr));
NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
NEW_AUX_ENT(AT_BASE, interp_load_addr);
NEW_AUX_ENT(AT_FLAGS, 0);
NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
NEW_AUX_ENT(AT_UID, (elf_addr_t) current->uid);
NEW_AUX_ENT(AT_EUID, (elf_addr_t) current->euid);
NEW_AUX_ENT(AT_GID, (elf_addr_t) current->gid);
NEW_AUX_ENT(AT_EGID, (elf_addr_t) current->egid);
if (k_platform) {
NEW_AUX_ENT(AT_PLATFORM, u_platform);
}
NEW_AUX_ENT(AT_NULL, 0);
#undef NEW_AUX_ENT
sp -= envc+1;
envp = (elf_caddr_t *) sp;
sp -= argc+1;
argv = (elf_caddr_t *) sp;
if (!ibcs) {
__put_user((elf_addr_t)(unsigned long) envp,--sp);
__put_user((elf_addr_t)(unsigned long) argv,--sp);
sp = STACK_ADD(p, ei_index);
items = (argc + 1) + (envc + 1);
if (interp_aout) {
items += 3; /* a.out interpreters require argv & envp too */
} else {
items += 1; /* ELF interpreters only put argc on the stack */
}
bprm->p = STACK_ROUND(sp, items);
/* Point sp at the lowest address on the stack */
#ifdef ARCH_STACK_GROWSUP
sp = (elf_addr_t *)bprm->p - items - ei_index;
bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */
#else
sp = (elf_addr_t *)bprm->p;
#endif
__put_user((elf_addr_t)argc,--sp);
current->mm->arg_start = (unsigned long) p;
while (argc-->0) {
__put_user((elf_caddr_t)(unsigned long)p,argv++);
len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);
/* Now, let's put argc (and argv, envp if appropriate) on the stack */
__put_user(argc, sp++);
if (interp_aout) {
argv = sp + 2;
envp = argv + argc + 1;
__put_user((elf_addr_t)argv, sp++);
__put_user((elf_addr_t)envp, sp++);
} else {
argv = sp;
envp = argv + argc + 1;
}
/* Populate argv and envp */
p = current->mm->arg_start;
while (argc-- > 0) {
size_t len;
__put_user((elf_addr_t)p, argv++);
len = strnlen_user((void *)p, PAGE_SIZE*MAX_ARG_PAGES);
if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
return NULL;
return;
p += len;
}
__put_user(NULL, argv);
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
while (envc-->0) {
__put_user((elf_caddr_t)(unsigned long)p,envp++);
len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);
current->mm->arg_end = current->mm->env_start = p;
while (envc-- > 0) {
size_t len;
__put_user((elf_addr_t)p, envp++);
len = strnlen_user((void *)p, PAGE_SIZE*MAX_ARG_PAGES);
if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
return NULL;
return;
p += len;
}
__put_user(NULL, envp);
current->mm->env_end = (unsigned long) p;
return sp;
current->mm->env_end = p;
/* Put the elf_info on the stack in the right place. */
sp = (elf_addr_t *)envp + 1;
copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t));
}
#ifndef elf_map
......@@ -438,7 +449,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
unsigned char ibcs2_interpreter = 0;
unsigned long error;
struct elf_phdr * elf_ppnt, *elf_phdata;
unsigned long elf_bss, k, elf_brk;
unsigned long elf_bss, elf_brk;
int elf_exec_fileno;
int retval, i;
unsigned int size;
......@@ -576,21 +587,17 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* OK, we are done with that, now set up the arg stuff,
and then start this sucker up */
if (!bprm->sh_bang) {
char * passed_p;
if (interpreter_type == INTERPRETER_AOUT) {
if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) {
char *passed_p = passed_fileno;
sprintf(passed_fileno, "%d", elf_exec_fileno);
passed_p = passed_fileno;
if (elf_interpreter) {
retval = copy_strings_kernel(1,&passed_p,bprm);
retval = copy_strings_kernel(1, &passed_p, bprm);
if (retval)
goto out_free_dentry;
bprm->argc++;
}
}
}
/* Flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
......@@ -603,7 +610,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->end_code = 0;
current->mm->mmap = NULL;
current->flags &= ~PF_FORKNOEXEC;
elf_entry = (unsigned long) elf_ex.e_entry;
/* Do this immediately, since STACK_TOP as used in setup_arg_pages
may depend on the personality. */
SET_PERSONALITY(elf_ex, ibcs2_interpreter);
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
......@@ -623,7 +633,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
int elf_prot = 0, elf_flags;
unsigned long vaddr;
unsigned long k, vaddr;
if (elf_ppnt->p_type != PT_LOAD)
continue;
......@@ -690,7 +700,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
elf_brk = k;
}
elf_entry += load_bias;
elf_ex.e_entry += load_bias;
elf_bss += load_bias;
elf_brk += load_bias;
start_code += load_bias;
......@@ -717,6 +727,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
send_sig(SIGSEGV, current, 0);
return 0;
}
} else {
elf_entry = elf_ex.e_entry;
}
kfree(elf_phdata);
......@@ -728,18 +740,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
bprm->p = (unsigned long)
create_elf_tables((char *)bprm->p,
bprm->argc,
bprm->envc,
&elf_ex,
load_addr, load_bias,
interp_load_addr,
(interpreter_type == INTERPRETER_AOUT ? 0 : 1));
create_elf_tables(bprm, &elf_ex, (interpreter_type == INTERPRETER_AOUT),
load_addr, interp_load_addr);
/* N.B. passed_fileno might not be initialized? */
if (interpreter_type == INTERPRETER_AOUT)
current->mm->arg_start += strlen(passed_fileno) + 1;
current->mm->start_brk = current->mm->brk = elf_brk;
current->mm->end_code = end_code;
current->mm->start_code = start_code;
current->mm->start_data = start_data;
......
......@@ -323,9 +323,50 @@ int setup_arg_pages(struct linux_binprm *bprm)
{
unsigned long stack_base;
struct vm_area_struct *mpnt;
struct mm_struct *mm = current->mm;
int i;
stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
#ifdef ARCH_STACK_GROWSUP
/* Move the argument and environment strings to the bottom of the
* stack space.
*/
int offset, j;
char *to, *from;
/* Start by shifting all the pages down */
i = 0;
for (j = 0; j < MAX_ARG_PAGES; j++) {
struct page *page = bprm->page[j];
if (!page)
continue;
bprm->page[i++] = page;
}
/* Now move them within their pages */
offset = bprm->p % PAGE_SIZE;
to = kmap(bprm->page[0]);
for (j = 1; j < i; j++) {
memmove(to, to + offset, PAGE_SIZE - offset);
from = kmap(bprm->page[j]);
memcpy(to + PAGE_SIZE - offset, from, offset);
kunmap(bprm[j - 1]);
to = from;
}
memmove(to, to + offset, PAGE_SIZE - offset);
kunmap(bprm[j - 1]);
/* Adjust bprm->p to point to the end of the strings. */
bprm->p = PAGE_SIZE * i - offset;
stack_base = STACK_TOP - current->rlim[RLIMIT_STACK].rlim_max;
mm->arg_start = stack_base;
/* zero pages that were copied above */
while (i < MAX_ARG_PAGES)
bprm->page[i++] = NULL;
#else
stack_base = STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
mm->arg_start = bprm->p + stack_base;
#endif
bprm->p += stack_base;
if (bprm->loader)
......@@ -341,19 +382,25 @@ int setup_arg_pages(struct linux_binprm *bprm)
return -ENOMEM;
}
down_write(&current->mm->mmap_sem);
down_write(&mm->mmap_sem);
{
mpnt->vm_mm = current->mm;
mpnt->vm_mm = mm;
#ifdef ARCH_STACK_GROWSUP
mpnt->vm_start = stack_base;
mpnt->vm_end = PAGE_MASK &
(PAGE_SIZE - 1 + (unsigned long) bprm->p);
#else
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
mpnt->vm_end = STACK_TOP;
#endif
mpnt->vm_page_prot = PAGE_COPY;
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_ops = NULL;
mpnt->vm_pgoff = 0;
mpnt->vm_file = NULL;
mpnt->vm_private_data = (void *) 0;
insert_vm_struct(current->mm, mpnt);
current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
insert_vm_struct(mm, mpnt);
mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
}
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
......@@ -364,7 +411,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
}
stack_base += PAGE_SIZE;
}
up_write(&current->mm->mmap_sem);
up_write(&mm->mmap_sem);
return 0;
}
......@@ -732,7 +779,6 @@ void compute_creds(struct linux_binprm *bprm)
security_ops->bprm_compute_creds(bprm);
}
void remove_arg_zero(struct linux_binprm *bprm)
{
if (bprm->argc) {
......@@ -854,7 +900,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
return retval;
}
/*
* sys_execve() executes a new program.
*/
......
......@@ -334,7 +334,6 @@ void ia64_elf32_init(struct pt_regs *regs);
#define ELF_PLAT_INIT(_r) ia64_elf32_init(_r)
#define elf_addr_t u32
#define elf_caddr_t u32
/* ELF register definitions. This is needed for core dump support. */
......
......@@ -31,7 +31,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
\
if (__h->e_machine != EM_MIPS) \
__res = 0; \
if (sizeof(elf_caddr_t) == 8 && \
if (sizeof(elf_addr_t) == 8 && \
__h->e_ident[EI_CLASS] == ELFCLASS32) \
__res = 0; \
\
......
......@@ -98,19 +98,14 @@ extern int ucache_bsize;
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
*/
#define DLINFO_ARCH_ITEMS 3
#define ARCH_DLINFO \
do { \
sp -= DLINFO_ARCH_ITEMS * 2; \
NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize); \
/* \
* Now handle glibc compatibility. \
*/ \
sp -= 2*2; \
NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
/* Now handle glibc compatibility. */ \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
} while (0)
#endif /* __KERNEL__ */
......
......@@ -31,13 +31,11 @@ typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
typedef elf_greg_t64 elf_greg_t;
typedef elf_gregset_t64 elf_gregset_t;
# define elf_addr_t unsigned long
# define elf_caddr_t char *
#else
/* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */
typedef elf_greg_t32 elf_greg_t;
typedef elf_gregset_t32 elf_gregset_t;
# define elf_addr_t u32
# define elf_caddr_t u32
#endif
typedef double elf_fpreg_t;
......@@ -122,19 +120,14 @@ extern int ucache_bsize;
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
*/
#define DLINFO_ARCH_ITEMS 3
#define ARCH_DLINFO \
do { \
sp -= DLINFO_ARCH_ITEMS * 2; \
NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize); \
/* \
* Now handle glibc compatibility. \
*/ \
sp -= 2*2; \
NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
/* Now handle glibc compatibility. */ \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
} while (0)
#endif /* __PPC64_ELF_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment