2014年7月29日 星期二

indirect function (IFUNC)

function attribute:
This allows the resolution of the symbol value to be determined dynamically at load time, and an optimized version of the routine can be selected for the particular processor or other system characteristics determined then.

NOTE:  require a recent binutils (at least version 2.20.1), and GNU C library (at least version 2.11.1).
ps. building arm static binary with using ld.gold linker has bug
https://sourceware.org/bugzilla/show_bug.cgi?id=17081


https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
https://gcc.gnu.org/ml/gcc-help/2012-03/msg00209.html



Real example:

glibc for armv7 has 3 type memcpy implementation.
  1. __memcpy_neon
  2. __memcpy_vfp
  3. memcpy_arm

memcpy (IFUNC):
  if (neon supported)
     return &__memcpy_neon
  if (vfp supported)
     return &__memcpy_vfp
  return &__memcpy_arm

memcpy will choose memcpy implementation at load time
memcpy use HWCP info (include CPU info) to got cpu capability

HWCAP(hardware capabilities)
#require executable file for system info
$LD_SHOW_AUXV=1 /lib/ld-linux-armhf.so.3

.got
ld-linux0 --> a.out's struct link map in ld-linux.so
ld-linux1 --> _dl_runtime_reolve in ld-linux.so

dynamic link的lazy binding
WHY? 呼叫.so function
HOW? GOT + PLT

第一次呼叫foo時, got內foo的address會指到ld-linux.so的dl_runtime_resolve
dl_runtime_resolve會把foo的address填到got內foo的address,然後跳到foo

第二次呼叫foo時, got內的foo的address就是指到foo, 就直接跳過去執行foo

Q: softfp的memcpy_vfp 跟 hardfp的memcpy_vfp的實做會一樣嗎?
A: libc有分不同版本, 所以沒問題

ifunc is indriect call

在static build的情況下
在main之前必須執行glibc apply_iplt去initialize ifunc

apply_iplt:
  for each R_ARM_IRELATIVE
     val = * GOT[i](hwcap);
     GOT[i] = val;


2014年7月28日 星期一

lvalue & rvalue

reference:
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
http://en.cppreference.com/w/cpp/language/value_category

An lvalue is an expression whose address can be taken

 You can make assignments to lvalues



1
2
3
4
5
6
7
int x;
int& getRef ()
{
        return x;
}
getRef() = 4;

A Rvalue is a temporary value.

You can't make assignments to lvalues


1
2
3
4
5
string getName ()
{
    return "Alex";
}
getName();



C++11 rvalue reference
let you bind a mutable reference to an rvalue
Rvalue references use the && syntax instead of just &, and can be const and non-const

1
2
const string&& name = getName(); // ok
string&& name = getName(); // also ok - praise be!

1
2
3
4
5
6
7
8
9
printReference (const String& str)
{
        cout << str;
}
printReference (String&& str)
{
        cout << str;
}

1
2
3
4
string me( "alex" );
printReference( me ); // calls the first printReference function, taking an lvalue reference
printReference( getName() ); // calls the second printReference function, taking a mutable rvalue reference


xvalue

An xvalue is an expression that identifies an "eXpiring" object, that is, the object that may be moved from. 

std::move

std::move obtains an rvalue reference to its argument and converts it to an xvalue.


std::make_unique

Constructs an object of type T and wraps it in a std::unique_ptr.

std::unique_ptr

std::unique_ptr is a smart pointer that retains sole ownership of an object through a pointer and destroys that object when the unique_ptr goes out of scope.
No two unique_ptr instances can manage the same object.

Example

#include <iostream>
#include <memory>
 
struct Foo
{
    Foo()      { std::cout << "Foo::Foo\n";  }
    ~Foo()     { std::cout << "Foo::~Foo\n"; }
    void bar() { std::cout << "Foo::bar\n";  }
};
 
void f(const Foo &)
{
    std::cout << "f(const Foo&)\n";
}
 
int main()
{
    std::unique_ptr<Foo> p1(new Foo);  // p1 owns Foo
    if (p1) p1->bar();
 
    {
        std::unique_ptr<Foo> p2(std::move(p1));  // now p2 owns Foo
        f(*p2);
 
        p1 = std::move(p2);  // ownership returns to p1
        std::cout << "destroying p2...\n";
    }
 
    if (p1) p1->bar();
 
    // Foo instance is destroyed when p1 goes out of scope
}
Output:
Foo::Foo
Foo::bar
f(const Foo&)
destroying p2...
Foo::bar
Foo::~Foo