142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes/*
242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * Copyright (C) 2013 The Android Open Source Project
342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *
442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * you may not use this file except in compliance with the License.
642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * You may obtain a copy of the License at
742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *
842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes *
1042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * Unless required by applicable law or agreed to in writing, software
1142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * See the License for the specific language governing permissions and
1442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes * limitations under the License.
1542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes */
1642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
1742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#ifndef KERNEL_ARGUMENT_BLOCK_H
1842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#define KERNEL_ARGUMENT_BLOCK_H
1942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
2042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#include <elf.h>
210266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes#include <link.h>
2242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#include <stdint.h>
2342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#include <sys/auxv.h>
2442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
258eac9af24ea7e570e0b297bcd6ac8a46ba3ecc39Elliott Hughes#include "private/bionic_macros.h"
268eac9af24ea7e570e0b297bcd6ac8a46ba3ecc39Elliott Hughes
270d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughesstruct abort_msg_t;
280d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes
2942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// When the kernel starts the dynamic linker, it passes a pointer to a block
3042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// of memory containing argc, the argv array, the environment variable array,
3142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// and the array of ELF aux vectors. This class breaks that block up into its
3242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes// constituents for easy access.
3342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughesclass KernelArgumentBlock {
3442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes public:
3542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  KernelArgumentBlock(void* raw_args) {
36c620059479c47a78d57086d73726c9adc2f337adElliott Hughes    uintptr_t* args = reinterpret_cast<uintptr_t*>(raw_args);
3742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    argc = static_cast<int>(*args);
3842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    argv = reinterpret_cast<char**>(args + 1);
3942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    envp = argv + argc + 1;
4042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
4142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    // Skip over all environment variable definitions to find aux vector.
4242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    // The end of the environment block is marked by two NULL pointers.
4342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    char** p = envp;
4442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    while (*p != NULL) {
4542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      ++p;
4642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    }
4742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    ++p; // Skip second NULL;
4842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
490266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes    auxv = reinterpret_cast<ElfW(auxv_t)*>(p);
5042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  }
5142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
5242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  // Similar to ::getauxval but doesn't require the libc global variables to be set up,
5342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  // so it's safe to call this really early on. This function also lets you distinguish
5442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  // between the inability to find the given type and its value just happening to be 0.
5542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  unsigned long getauxval(unsigned long type, bool* found_match = NULL) {
560266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes    for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) {
5742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      if (v->a_type == type) {
5842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes        if (found_match != NULL) {
5942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes            *found_match = true;
6042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes        }
6142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes        return v->a_un.a_val;
6242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      }
6342b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    }
6442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    if (found_match != NULL) {
6542b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes      *found_match = false;
6642b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    }
6742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes    return 0;
6842b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  }
6942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
7042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  int argc;
7142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  char** argv;
7242b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes  char** envp;
730266ae5f884d72da58f33a072e865ba131234a5eElliott Hughes  ElfW(auxv_t)* auxv;
7442b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
750d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes  abort_msg_t** abort_message_ptr;
760d787c1fa18c6a1f29ef9840e28a68cf077be1deElliott Hughes
7742b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes private:
788eac9af24ea7e570e0b297bcd6ac8a46ba3ecc39Elliott Hughes  DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock);
7942b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes};
8042b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes
8142b2c6a5eed5e4ef35315b8cd32d1355f12a69b6Elliott Hughes#endif // KERNEL_ARGUMENT_BLOCK_H
82