My goal is to write to the coprocessor p15 register, and right now I'm just trying to read it.
I have the following example c++ program, the first asm instruction is just a simple ror, which works just fine. The second asm instruction, I'm trying to just read SCTLR register.
I compile the program with g++ test_program.cpp -o test
and run with ./test or sudo ./test
If I run with ./test, I get the output:
Value: 10 Result: 8
Illegal instruction
If I run with sudo ./test, I get:
Value: 10 Result: 8
So clearly the instruction is not working since its not printing the line "got here" or "SCTLR". Is there something else I have to do to execute the coprocessor read? I'm running this on a raspberry pi (Cortex A-53).
#include <cstdlib>
#include <cstdio>
int main(){
unsigned int y, x;
x = 16;
//Assembly rotate right 1 example
asm("mov %[result], %[value], ror #1"
: [result]"=r" (y) /* Rotation result. */
: [value]"r" (x) /* Rotated value. */
: /* No clobbers */
);
printf("Value: %x Result: %x\n", x, y);
// Assembly read SCTLR, program crashes if this is run
unsigned int id = 0;
asm("MRC p15, 0, %[result], c0, c0, 0"
: [result]"=r" (id) //Rotation result.
);
printf("Got here\n");
printf("SCTLR: %x", id);
return 0;
}
Related
I am using the Intel PIN tool to emulate some new instructions and check the corresponding results. For this purpose I am using illegal opcodes of x86_64 to represent my instructions. For example- opcodes 0x16, 0x17 are illegal in x86_64. which represent my instruction opcodes. I am using a C program to generate an executable and then pass it to the Pintool. A C program I am using is this -
#include <stdio.h>
int main()
{
asm(".byte 0x16");
asm(".byte 0x17");
return 0;
}
So if we see the instruction trace 0x16 and 0x17 will appear as bad instructions and if we try to run the executable we get -
Illegal instruction (core dumped)
which is expected as 0x16, 0x17 are illegal in x86_64 and hence the executable should not pass. I am using this executable as input to my Pintool, which examines the instruction trace and hence will encounter 0x16 and 0x17 in the trace.
The Pintool I am using is this -
#include "pin.H"
#include <iostream>
#include <fstream>
#include <cstdint>
UINT64 icount = 0;
using namespace std;
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", "test.out","This pin tool simulates ULI");
FILE * op;
//====================================================================
// Analysis Routines
//====================================================================
VOID simulate_ins(VOID *ip, UINT32 size) {
fprintf(op,"Wrong instruction encountered here\n");
// Do something based on the instruction
}
//====================================================================
// Instrumentation Routines
//====================================================================
VOID Instruction(INS ins, void *v) {
UINT8 opcodeBytes[15];
UINT64 fetched = PIN_SafeCopy(&opcodeBytes[0],(void *)INS_Address(ins),INS_Size(ins));
if (fetched != INS_Size(ins))
fprintf(op,"\nBad\n");
else {
if(opcodeBytes[0]==0x16 || opcodeBytes[0]==0x17) {
INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)simulate_ins, IARG_INST_PTR, IARG_UINT64, INS_Size(ins) , IARG_END);
INS_Delete(ins);
}
}
VOID Fini(INT32 code, VOID *v) {
//Display some end result
}
INT32 Usage() {
PIN_ERROR("This Pintool failed\n" + KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
int main(int argc, char *argv[])
{
op = fopen("test.out", "w");
if (PIN_Init(argc, argv))
return Usage();
PIN_InitSymbols();
PIN_AddInternalExceptionHandler(ExceptionHandler,NULL);
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
PIN_StartProgram();
return 0;
}
So I am extracting my assembly opcodes and if the first byte is 0x16 or 0x17 I am sending the instruction to my analysis routine and then deleting the instruction. But however when I run this Pintool on the executable I still get the Illegal instruction (core dumped) error and my code fails to run. My understanding is that the Instrumentation routine is called every time a new instruction is encountered in the trace and the analysis routine is called before the instruction is executed. Here I am checking for the opcode and based on the result I am sending the code to the analysis routine and deleting the instruction. I will be simulating my new instruction in the analysis routine so, I just need to delete the old instruction and let the program proceed futher and make sure it dosen't give the illegal instruction error again.
Anywhere I am doing something wrong?
In a C++ program, under Windows 7 using VS2013 and under Ubuntu 14.04.1 using g++ 4.6, I am mystified by the operation of printf().
With the 2nd width modifier, this prints a space instead of a 0.
When set to another value, e.g., -1, it prints it. Without the modifier, it prints a 0, as expected.
I pasted the actual, relevant code into another program and it behaved the same way.
What could be the problem?
#include <stdio.h>
int main(){
int x = 1, z = 0;
printf ("%2.d: %2.d\n", x, z); // fails to print 0
printf ("%2.d: %d\n", x, z); // 2nd %2. absent, prints as expected
return 0;
}
Output:
1:
1: 0
The point should go to the left
#include <stdio.h>
int main()
{
int x = 1, z = 0;
printf ("%.2d: %.2d\n", x, z); // fails to print 0
printf ("%.2d: %d\n", x, z); // 2nd %2. absent, prints as expected
return 0;
}
Output:
01: 00
01: 0
I prepared a C++ interface to a legacy Fortran library.
Some subroutines in the legacy library follow an ugly but usable status code convention to report errors, and I use such status codes to throw a readable exception from my C++ code: it works great.
On the other hand, sometimes the legacy library calls STOP (which terminates the program). And it often does it even though the condition is recoverable.
I would like to capture this STOP from within C++, and so far I have been unsuccessful.
The following code is simple, but exactly represents the problem at hand:
The Fortran legacy library fmodule.f90:
module fmodule
use iso_c_binding
contains
subroutine fsub(x) bind(c, name="fsub")
real(c_double) x
if(x>=5) then
stop 'x >=5 : this kills the program'
else
print*, x
end if
end subroutine fsub
end module fmodule
The C++ Interface main.cpp:
#include<iostream>
// prototype for the external Fortran subroutine
extern "C" {
void fsub(double& x);
}
int main() {
double x;
while(std::cin >> x) {
fsub(x);
}
return 0;
}
The compilation lines (GCC 4.8.1 / OS X 10.7.4; $ denotes command prompt ):
$ gfortran -o libfmodule.so fmodule.f90 -shared -fPIC -Wall
$ g++ main.cpp -L. -lfmodule -std=c++11
The run:
$ ./a.out
1
1.0000000000000000
2
2.0000000000000000
3
3.0000000000000000
4
4.0000000000000000
5
STOP x >=5 : this kills the program
How could I capture the STOP and, say, request another number. Notice that I do not want to touch the Fortran code.
What I have tried:
std::atexit: cannot "come back" from it once I have entered it
std::signal: STOP does not seem to throw a signal which I can capture
You can solve your problem by intercepting the call to the exit function from the Fortran runtime. See below. a.out is created with your code and the compilation lines you give.
Step 1. Figure out which function is called. Fire up gdb
$ gdb ./a.out
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
[...]
(gdb) break fsub
Breakpoint 1 at 0x400888
(gdb) run
Starting program: a.out
5
Breakpoint 1, 0x00007ffff7dfc7e4 in fsub () from ./libfmodule.so
(gdb) step
Single stepping until exit from function fsub,
which has no line number information.
stop_string (string=0x7ffff7dfc8d8 "x >=5 : this kills the programfmodule.f90", len=30) at /usr/local/src/gcc-4.7.2/libgfortran/runtime/stop.c:67
So stop_string is called. We need to know to which symbol this function corresponds.
Step 2. Find the exact name of the stop_string function. It must be in one of the shared libraries.
$ ldd ./a.out
linux-vdso.so.1 => (0x00007fff54095000)
libfmodule.so => ./libfmodule.so (0x00007fa31ab7d000)
libstdc++.so.6 => /usr/local/gcc/4.7.2/lib64/libstdc++.so.6 (0x00007fa31a875000)
libm.so.6 => /lib64/libm.so.6 (0x0000003da4000000)
libgcc_s.so.1 => /usr/local/gcc/4.7.2/lib64/libgcc_s.so.1 (0x00007fa31a643000)
libc.so.6 => /lib64/libc.so.6 (0x0000003da3c00000)
libgfortran.so.3 => /usr/local/gcc/4.7.2/lib64/libgfortran.so.3 (0x00007fa31a32f000)
libquadmath.so.0 => /usr/local/gcc/4.7.2/lib64/libquadmath.so.0 (0x00007fa31a0fa000)
/lib64/ld-linux-x86-64.so.2 (0x0000003da3800000)
I found it in (no surprise) the fortran runtime.
$ readelf -s /usr/local/gcc/4.7.2/lib64/libgfortran.so.3|grep stop_string
1121: 000000000001b320 63 FUNC GLOBAL DEFAULT 11 _gfortran_stop_string##GFORTRAN_1.0
2417: 000000000001b320 63 FUNC GLOBAL DEFAULT 11 _gfortran_stop_string
Step 3. Write a function that will replace that function
I look for the precise signature of the function in the source code (/usr/local/src/gcc-4.7.2/libgfortran/runtime/stop.c see gdb session)
$ cat my_exit.c
#define _GNU_SOURCE
#include <stdio.h>
void _gfortran_stop_string (const char *string, int len)
{
printf("Let's keep on");
}
Step 4. Compile a shared object exporting that symbol.
gcc -Wall -fPIC -c -o my_exit.o my_exit.c
gcc -shared -fPIC -Wl,-soname -Wl,libmy_exit.so -o libmy_exit.so my_exit.o
Step 5. Run the program with LD_PRELOAD so that our new function has precedence over the one form the runtime
$ LD_PRELOAD=./libmy_exit.so ./a.out
1
1.0000000000000000
2
2.0000000000000000
3
3.0000000000000000
4
4.0000000000000000
5
Let's keep on 5.0000000000000000
6
Let's keep on 6.0000000000000000
7
Let's keep on 7.0000000000000000
There you go.
Since what you want would result in non-portable code anyway, why not just subvert the exit mechanism using the obscure long jump mechanism:
#include<iostream>
#include<csetjmp>
#include<cstdlib>
// prototype for the external Fortran subroutine
extern "C" {
void fsub(double* x);
}
volatile bool please_dont_exit = false;
std::jmp_buf jenv;
static void my_exit_handler() {
if (please_dont_exit) {
std::cout << "But not yet!\n";
// Re-register ourself
std::atexit(my_exit_handler);
longjmp(jenv, 1);
}
}
void wrapped_fsub(double& x) {
please_dont_stop = true;
if (!setjmp(jenv)) {
fsub(&x);
}
please_dont_stop = false;
}
int main() {
std::atexit(my_exit_handler);
double x;
while(std::cin >> x) {
wrapped_fsub(x);
}
return 0;
}
Calling longjmp jumps right in the middle of the line with the setjmp call and setjmp returns the value passed as the second argument of longjmp. Otherwise setjmp returns 0. Sample output (OS X 10.7.4, GCC 4.7.1):
$ ./a.out
2
2.0000000000000000
6
STOP x >=5 : this kills the program
But not yet!
7
STOP x >=5 : this kills the program
But not yet!
4
4.0000000000000000
^D
$
No library preloading required (which anyway is a bit more involved on OS X than on Linux). A word of warning though - exit handlers are called in reverse order of their registration. One should be careful that no other exit handlers are registered after my_exit_handler.
Combining the two answers that use a custom _gfortran_stop_string function and longjmp, I thought that raising an exception inside the custom function would be similar, then catch in in the main code. So this came out:
main.cpp:
#include<iostream>
// prototype for the external Fortran subroutine
extern "C" {
void fsub(double& x);
}
int main() {
double x;
while(std::cin >> x) {
try { fsub(x); }
catch (int rc) { std::cout << "Fortran stopped with rc = " << rc <<std::endl; }
}
return 0;
}
catch.cpp:
extern "C" {
void _gfortran_stop_string (const char*, int);
}
void _gfortran_stop_string (const char *string, int len)
{
throw 666;
}
Then, compiling:
gfortran -c fmodule.f90
g++ -c catch.cpp
g++ main.cpp fmodule.o catch.o -lgfortran
Running:
./a.out
2
2.0000000000000000
3
3.0000000000000000
5
Fortran stopped with rc = 666
6
Fortran stopped with rc = 666
2
2.0000000000000000
3
3.0000000000000000
^D
So, seems to work :)
I suggest you fork your process before calling the fortran code and exit 0 (edit: if STOP exits with zero, you will need a sentinel exit code, clanky but does the job) after the fortran execution. That way every fortran call will finish in the same way: the same as if it had stopped. Or, if "STOP" ensure an error, throw the exception when the fortran code stops and send some other message when the fortran execution "completes" normaly.
Below is an example inspire from you code assuming a fortran "STOP" is an error.
int main() {
double x;
pid_t pid;
int exit_code_normal = //some value that is different from all STOP exit code values
while(std::cin >> x) {
pid = fork();
if(pid < 0) {
// error with the fork handle appropriately
} else if(pid == 0) {
fsub(x);
exit(exit_code_normal);
} else {
wait(&status);
if(status != exit_code_normal)
// throw your error message.
}
}
return 0;
}
The exit code could be a constant instead of a variable. I don't think it matters much.
Following a comment, it occurs that the result from the execution would be lost if it sits in the memory of the process (rather than, say, write to a file). If it is the case, I can think of 3 possibilities:
The fortran code messes a whole lot of memory during the call and letting the execution continue beyond the STOP is probably not a good idea in the first place.
The fortran code simply return some value (through it's argument if my fortran is not too rusty) and this could be relayed back to the parent easily through a shared memory space.
The execution of the fortran subroutine acts on an external system (ex: writes to a file) and no return values are expected.
In the 3rd case, my solution above works as is. I prefer it over some other suggested solution mainly because: 1) you don't have to ensure the build process is properly maintained 2) fortran "STOP" still behave as expected and 3) it requires very few lines of code and all the "fortran STOP workaround" logic sits in one single place. So in terms of long term maintenance, I much prefer that.
In the 2nd case, my code above needs small modification but still holds the advantages enumerated above at the price of minimal added complexity.
In the 1st case, you will have to mess with the fortran code no matter what.
This code compiles and runs though gives a Microsoft compiler error that I cant fix
warning C4700: uninitialized local variable '' used.
This is in the last line of the code, I think
#include <iostream>
using namespace std;
const int DIM0 = 2, DIM1 = 3, DIM2 = 4, DIM3 = 5;
void TestDeclar();
int main(){
TestDeclar();
cout << "Done!\n";
return 0;
}
void TestDeclar(){
//24 - array of 5 floats
float xa[DIM3], xb[DIM3], xc[DIM3], xd[DIM3], xe[DIM3], xf[DIM3];
float xg[DIM3], xh[DIM3], xi[DIM3], xj[DIM3], xk[DIM3], xl[DIM3];
float xm[DIM3], xn[DIM3], xo[DIM3], xp[DIM3], xq[DIM3], xr[DIM3];
float xs[DIM3], xt[DIM3], xu[DIM3], xv[DIM3], xw[DIM3], xx[DIM3];
//6 - array of 4 pointers to floats
float *ya[DIM2] = {xa, xb, xc, xd}, *yb[DIM2] = {xe, xf, xg, xh};
float *yc[DIM2] = {xi, xj, xk, xl}, *yd[DIM2] = {xm, xn, xo, xp};
float *ye[DIM2] = {xq, xr, xs, xt}, *yf[DIM2] = {xu, xv, xw, xx};
//2 - array of 3 pointers to pointers of floats
float **za[DIM1] = {ya, yb, yc};
float **zb[DIM1] = {yd, ye, yf};
//array of 2 pointers to pointers to pointers of floats
float ***ptr[DIM0] = {za, zb};
cout << &***ptr[DIM0] << '\n';
}
You're accessing past the end of the ptr4D. DIM0 is 2, one greater than the last index of 1!
Change the last few lines to:
//array of 2 pointers to pointers to pointers of floats
float ***ptr4D[DIM0] = {za, zb};
cout << &***ptr4D[0] << '\n';
Not sure if I can help you but I tried to find out what's wrong trying to run it on my linux machine. I've compiled it on a ubuntu machine to compare and it went ok, even tellign the compiler to turn on all option warnings (passing the -Wall option). When running, I got this:
# Compiled it with -Wall to enable all warning flags and -g3 to produce extra debug information
~$ g++ -Wall stackoverflow.cpp -g3
./a.out
Segmentation fault (core dumped)
Then I've tried to debug it with GDB (GNU debugger) and got this:
(gdb) r
Starting program: /home/ubuntu/a.out
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400986 in TestDeclar () at stackoverflow.cpp:34
34 cout << &***ptr4D[DIM0] << '\n';
(gdb) s
So it appears that the problem is at the cout line. Checking your code again, DIM0's value is 2, so you're trying to access a memory address beyond the ptr4D. As user1721424 mentioned, just replace the DIM0 with 0 and it's done!
#After fixing it:
~$ ./a.out
0x7fff74cd3830
Done!
Hope it helps!
It feels like I'm abusing Stackoverflow with all my questions, but it's a Q&A forum after all :) Anyhow, I have been using detours for a while now, but I have yet to implement one of my own (I've used wrappers earlier). Since I want to have complete control over my code (who doesn't?) I have decided to implement a fully functional detour'er on my own, so I can understand every single byte of my code.
The code (below) is as simple as possible, the problem though, is not. I have successfully implemented the detour (i.e a hook to my own function) but I haven't been able to implement the trampoline.
Whenever I call the trampoline, depending on the offset I use, I get either a "segmentation fault" or an "illegal instruction". Both cases ends the same though; 'core dumped'. I think it is because I've mixed up the 'relative address' (note: I'm pretty new to Linux so I have far from mastered GDB).
As commented in the code, depending on sizeof(jmpOp)(at line 66) I either get an illegal instruction or a segmentation fault. I'm sorry if it's something obvious, I'm staying up way too late...
// Header files
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include "global.h" // Contains typedefines for byte, ulong, ushort etc...
#include <cstring>
bool ProtectMemory(void * addr, int flags)
{
// Constant holding the page size value
const size_t pageSize = sysconf(_SC_PAGE_SIZE);
// Calculate relative page offset
size_t temp = (size_t) addr;
temp -= temp % pageSize;
// Update address
addr = (void*) temp;
// Update memory area protection
return !mprotect(addr, pageSize, flags);
}
const byte jmpOp[] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
int Test(void)
{
printf("This is testing\n");
return 5;
}
int MyTest(void)
{
printf("This is ******\n");
return 9;
}
typedef int (*TestType)(void);
int main(int argc, char * argv[])
{
// Fetch addresses
byte * test = (byte*) &Test;
byte * myTest = (byte*) &MyTest;
// Call original
Test();
// Update memory access for 'test' function
ProtectMemory((void*) test, PROT_EXEC | PROT_WRITE | PROT_READ);
// Allocate memory for the trampoline
byte * trampoline = new byte[sizeof(jmpOp) * 2];
// Do copy operations
memcpy(trampoline, test, sizeof(jmpOp));
memcpy(test, jmpOp, sizeof(jmpOp));
// Setup trampoline
trampoline += sizeof(jmpOp);
*trampoline = 0xE9;
// I think this address is incorrect, how should I calculate it? With the current
// status (commented 'sizeof(jmpOp)') the compiler complains about "Illegal Instruction".
// If I uncomment it, and use either + or -, a segmentation fault will occur...
*(uint*)(trampoline + 1) = ((uint) test - (uint) trampoline)/* + sizeof(jmpOp)*/;
trampoline -= sizeof(jmpOp);
// Make the trampoline executable (and read/write)
ProtectMemory((void*) trampoline, PROT_EXEC | PROT_WRITE | PROT_READ);
// Setup detour
*(uint*)(test + 1) = ((uint) myTest - (uint) test) - sizeof(jmpOp);
// Call 'detoured' func
Test();
// Call trampoline (crashes)
((TestType) trampoline)();
return 0;
}
In case of interest, this is the output during a normal run (with the exact code above):
This is testing
This is **
Illegal instruction (core dumped)
And this is the result if I use +/- sizeof(jmpOp) at line 66:
This is testing
This is ******
Segmentation fault (core dumped)
NOTE: I'm running Ubuntu 32 bit and compile with g++ global.cpp main.cpp -o main -Iinclude
You're not going to be able to indiscriminately copy the first 5 bytes of Test() into your trampoline, followed by a jump to the 6th instruction byte of Test(), because you don't know if the first 5 bytes comprise an integral number of x86 variable-length instructions. To do this, you're going to have to do at least a minimal amount of automated disassembling of the Test() function in order to find an instruction boundary that's 5 or more bytes past the beginning of the function, then copy an appropriate number of bytes to your trampoline, and THEN append your jump (which won't be at a fixed offset within your trampoline). Note that on a typical RISC processor (like PPC), you wouldn't have this problem, as all instructions are the same width.