Possible conversion from C time_t to string

Using the llvm pass, I instrumented printf to C/CPP codes. Now, I want to print UNIX time but am stuck on a simple problem. I am using CPP time_t to print it, but to print it at runtime, I have to convert it to a string. There is no possible conversion from time_t to StringRef/raw_string_ostream. Any suggestions how to pass it to the CreateGlobalStringPtr(). Thanks in advance.

// Injecting World time
                                std::time_t now = std::time(0);
                                char* dt = ctime(&now);
                                errs()<<"dt: "<<dt<<"Unix time: "<<now<<"\n";

                                // date and time
                                Value *str = builder.CreateGlobalStringPtr(dt, "str");
                                std::vector<Value *> worldClock({str});
                                builder.CreateCall(printfFunc, worldClock, "calltmp");

                                // Unix time
                                raw_string_ostream rsoT(now);
                                Value *unixT = builder.CreateGlobalStringPtr(rsoT, "str");
                                std::vector<Value *> unixTime({unixT});
                                builder.CreateCall(printfFunc, unixTime, "calltmp");

You don’t. Take a big step back and think about the fundamental difference between compile-time constants and run-time variables.

1 Like

Thank you for your reply. But I didn’t quite understand what you meant by the compile-time constants and run-time variables. Compile-time constants are computed at the time the code is compiled, while a runtime constant is computed during runtime. And there are 3 different runtime variables. But what is the relation of these 2 with the time_t variable, are you saying this is a runtime variable, but to pass it to print, it should be a string and as it is not, CreateGlobalStringPtr is giving this error,

error: no viable conversion from 'std::time_t' (aka 'long') to 'llvm::StringRef'
Value *unixT = builder.CreateGlobalStringPtr(now, "str");

Well I’m assuming your goal is “I want to print the time that my instrumented function is called”, which would mean that the time is a run-time value, because it’s changing and only known when the function is called, not when your compiler pass runs to inject instrumentation. The code you currently have looks like it’s trying to do “print the time that my compiler pass processed that code when my instrumented function is called”. That is, if you compile some file with instrumentation today, 24th January, it will always print out 24th January when you run the resulting binary, which doesn’t seem particularly useful.

If, however, you really want to write code that does the latter, ctime is one way to convert from a time_t to a char *, and you can then wrap that in a StringRef and pass it to CreateGlobalStringPtr. Just be careful about the fact that ctime uses a shared buffer and so isn’t thread-safe, and a subsequent call to ctime in the same thread will clobber it, so you must pass it to CreateGlobalStringPtr before anything clobbers it. Note that StringRef does not own the string, it’s just a reference to an existing one, same as a normal pointer. CreateGlobalStringPtr does, however, make a copy of the input.

1 Like

Yes, that’s my initial idea, but it is printing at different times while different functions are called. I am guessing this is because the print is calling variable worldClock which contains dt and the dt is calling ctime. That’s why time is different. But as you are saying if I want to print the time at runtime then I have to instrument this piece of code at inside a code,

std::time_t now = std::time(0);
char* dt = ctime(&now);
printf(time);

Instrumenting print is different than this one. I am not sure how to do this. Can you please give me some ideas?

Ok, I tried using ctime but it prints the time in “day, month, date, time” format. But I wanted to print the UNIX time. I solved it; it is simple; I have used the stringstream which gave me a string.

But most importantly, can you give me any suggestions on how to insert the time function using passes? Here is a simple comparison between two functions, printf and time_t,

This is a simple print in C,
printf("Value INT - %d\n", value_INT);
And this is what I did for inserting this, at first got the type in 32-bit as I will be instrumenting this to a 32-bit OS. Then got the list of arguments using vector, then the function type, and then inserted using getOrInsertFunction,

Type *intType = Type::getInt32Ty(context);
std::vector<Type *> printfArgsTypes({Type::getInt8PtrTy(context)});
FunctionType *printfType = FunctionType::get(intType, printfArgsTypes, true);
auto printfFunc = M.getOrInsertFunction("printf", printfType);

But here is what we have for time_t,

time_t now = std::time(0);
char* dt = ctime(&now);
printf("%s\n", dt);
  1. I am not sure if I need to declare a data type but how do I declare a data type of type time_t?
  2. how to call this std function time()?
  3. how to call ctime function?
  4. At last, pass this variable to printf.

I can simply insert the print where I will call the time and this should add the value there,
like instead of this,

std::time_t now = std::time(0);
char* dt = ctime(&now);
printf(time);

I will simply do this in pass,

printf("%ld\n",time(0));

This will work, but I have inserted it in the way I have created the print function, as shown above. But I am interested in knowing “how can I define a variable, assign values to the variable, and run a loop at runtime?” Any suggestions on where to start?