How to get source location of #includes using clang libtooling? - include

Is there any way to get clang::SourceLocation for every #include in file by its clang::FileID or clang::FileEntry or something?

What about using source manager's GetIncludedLoc function which takes fileid as parameter.
SourceManager.GetIncludedLoc(fileid)

Thank's #Hemant for your answer, you're right
I Already found that by myself (in clang 3.8 it is called getIncludeLoc)
but forgot to write here.
I used this to find the location after all #includes where i can put my own.
Here's the function (For sure not the best way) I wrote for this, hope it helps someone
SourceLocation getIncludeLocation(FileID fileID, SourceManager &sm, unsigned carriages) {
return SourceLocation();
set<unsigned> lines;
if (fileID.isInvalid())
for (auto it = sm.fileinfo_begin(); it != sm.fileinfo_end(); it++) {
SourceLocation includeLoc = sm.getIncludeLoc(sm.translateFile(it->first));
if (includeLoc.isValid() && sm.isInFileID(includeLoc, fileID)) {
lines.insert(sm.getSpellingLineNumber(includeLoc));
}
}
unsigned pos(0);
if (!lines.empty()) {
bool first = true;
for (unsigned line :lines) {
if (first)
first = false;
else if ((line - pos) > carriages)
break;
pos = line;
//cout << "Include line:" << pos << endl;
}
//cout << console_hline('-') << endl;
}
cout << sm.getFileEntryForID(fileID)->getName() << endl;
return sm.translateFileLineCol(sm.getFileEntryForID(fileID), ++pos, 1);
}
Also some information about includes can be get by
Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)
and
Lexer::ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0)

Related

libzip: zip_name_locate() fails on specific filename, even trying all possible encoding combinations

I am trying to build a "failsafe" layer on top of libzip but libzip is giving me some trouble here.
First I add a file to my (empty) archive with zip_file_add(...). This has 3 possible user-defined encodings available. Then I try to locate the name with zip_name_locate(...) which also has 3 possible user-defined encodings available.
This mcve checks all possible encoding combinations and all of them fail for the specific filename x%²»Ã-ØÑ–6¨wx.txt. When using a more conventional file.txt filename, zip_name_locate() succeeds every time.
#include <zip.h>
#include <include/libzip.h>//<.pragmas to include the .lib's...
#include <iostream>
#include <vector>
#include <utility>
/*
'zip_file_add' possible encodings:
ZIP_FL_ENC_GUESS
ZIP_FL_ENC_UTF_8
ZIP_FL_ENC_CP437
'zip_name_locate' possible encodings:
ZIP_FL_ENC_RAW
ZIP_FL_ENC_GUESS
ZIP_FL_ENC_STRICT
*/
/*
build encoding pairs (trying all possibilities)
*/
std::vector<std::pair<unsigned, unsigned>>
encoding_pairs{
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_RAW },
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_GUESS },
{ ZIP_FL_ENC_GUESS, ZIP_FL_ENC_STRICT },
{ ZIP_FL_ENC_UTF_8, ZIP_FL_ENC_STRICT },
{ ZIP_FL_ENC_CP437, ZIP_FL_ENC_STRICT },
};
int main(int argc, char** argv) {
const char* file_buf = "hello world";
#if 0
const char* file_name = "file.txt";
#else
const char* file_name = "x%²»Ã-ØÑ–6¨wx.txt";
#endif
zip_error_t ze;
zip_error_init(&ze);
{
zip_source_t* zs = zip_source_buffer_create(nullptr, 0, 1, &ze);
if (zs == NULL)
return -1;
zip_t* z = zip_open_from_source(zs, ZIP_CHECKCONS, &ze);
if (z == NULL)
return -1;
{
zip_source_t* s = zip_source_buffer(z, file_buf, strlen(file_buf), 0);//0 = don't let libzip auto-free the const char* buffer on the stack
if (s == NULL)
return -1;
for (size_t ep = 0; ep < encoding_pairs.size(); ep++) {
std::cout << "ep = " << ep << std::endl;
zip_uint64_t index;
if ((index = zip_file_add(z, file_name, s, encoding_pairs[ep].first)) == -1) {
std::cout << "could not zip_file_add() with encoding " << encoding_pairs[ep].first << std::endl;
continue;
}
if (zip_name_locate(z, file_name, encoding_pairs[ep].second) == -1) {
std::cout << "the name '" << file_name << "' could not be located." << std::endl;
std::cout << " encoding pair: " << encoding_pairs[ep].first << " <-> " << encoding_pairs[ep].second << std::endl;
}
else {
std::cout << "the name was located." << std::endl;
}
if (zip_delete(z, index) == -1)
return -1;
}
}
zip_close(z);
}
zip_error_fini(&ze);
return 0;
}
I don't understand what I might be doing wrong here or if libzip just can't even resolve such a name.
If it can't then what would be the criteria on names to avoid ?
It turns out the problem was the encoding of my source file itself. It was ANSI - So I converted it to UTF8 and it solved the issue.
What I still don't understand is why libzip can't zip_name_locate() a name from an input c-string that is exactly the same as the input c-string used in zip_file_add() (whatever the source file encoding might be). "Lost in translation" perhaps ?
(Special thanks to Thomas Klausner for helping me find the issue).

SEH with RtlAddFunctionTable in manually loaded DLL

I'm manually mapping a dll into a process which is compiled with (/EHa). This can catch exceptions like the one below. The problem is, since im manually mapping the dll the exceptions/functions are not registered which leads to a crash of the program as soon as a excpetion occurs. To solve this issue i came to the conclusion that i need to use this function "RtlAddFunctionTable(...)". Sadly im unable to get the first two parameters (FunctionTable and EntryCount) to call the function. Can someone help me out and tell me how i can get the first two parameters?
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
RUNTIME_FUNCTION runtimeFunction = ?;
DWORD size = ?;
RtlAddFunctionTable(&runtimeFunction, size, (DWORD64)hModule);
try
{
int var = *reinterpret_cast<int*>(0xFFFF);
}
catch (...)
{
cout << "Exception" << endl;
}
return TRUE;
}
Edit, i solved it:
bool EnableExceptions(DWORD64 moduleBase)
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader;
pDOSHeader = (PIMAGE_DOS_HEADER)moduleBase;
if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
return false;
pNTHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDOSHeader + pDOSHeader->e_lfanew);
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
return false;
pOptHeader = (PIMAGE_OPTIONAL_HEADER)& pNTHeader->OptionalHeader;
if (pOptHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
return false;
PRUNTIME_FUNCTION pFunctionTable = (PRUNTIME_FUNCTION)((DWORD64)pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress + moduleBase);
cout << "functionTable " << hex << functionTable << endl;
DWORD sizeFunctionTable = (pOptHeader->DataDirectory[3].Size / (DWORD)sizeof(RUNTIME_FUNCTION));
cout << "functionTableSize " << dec << functionTableSize << endl;
BOOL success = RtlAddFunctionTable(pFunctionTable, sizeFunctionTable, moduleBase);
cout << "RtlAddFunctionTable " << success << endl;
return success;
}
Since you are building the .DLL with SEH enabled the information you need should already be in the PE file.
According to this blog post, static tables in the PE takes precedence over dynamically added tables.
If you need to use a custom table for some reason then you need to use VirtualAlloc to allocate memory for the table and the code because the addresses are relative (RVA).

how to get char* filename from boost path

for (fs::directory_iterator iter(realPath); iter != end_iter; ++iter )
{
if (iter->path().extension() == ".png"){
fs::path currentPath = iter->path();
const char *filename = const_cast<char*>(currentPath.string().c_str());
std::cout << iter->path().leaf() << std::endl;
processFile(filename);
std::cout <<"Hi" << std::endl;
}
}
This is my code and here processFile functions accepts the filename in char* format. Above code returns a junk value of filename. Don't know what is the best way to get the filename.
It works fine for me here (Boost.1.52, Mac OS X, clang).
Though I have to agree with Miguel, you're doing way to much work here.
for (fs::directory_iterator iter(realPath); iter != end_iter; ++iter )
if (iter->path().extension() == ".png") {
fs::path currentPath = iter->path();
std::cout << currentPath.leaf() << std::endl;
processFile(currentPath.c_str ());
}
and depending on your taste in code, you could get rid of currentPath altogether ( replace it with iter->path() )

What Time Is This Returning

Deep in the sauce here. I haven't worked with time to much so I'm a little confused here. I know there is FILETIME and SYSTEMTIME. What I am trying to get at this point (because it might change) are file that are less than a 20 seconds old. This returning the files and their size and something in seconds, What I'd like to know is where it is filtering by time if it is, and how can I adjust it to suit my needs. Thank you.
using namespace std;
typedef vector<WIN32_FIND_DATA> tFoundFilesVector;
std::wstring LastWriteTime;
int getFileList(wstring filespec, tFoundFilesVector &foundFiles)
{
WIN32_FIND_DATA findData;
HANDLE h;
int validResult=true;
int numFoundFiles = 0;
h = FindFirstFile(filespec.c_str(), &findData);
if (h == INVALID_HANDLE_VALUE)
return 0;
while (validResult)
{
numFoundFiles++;
foundFiles.push_back(findData);
validResult = FindNextFile(h, &findData);
}
return numFoundFiles;
}
void showFileAge(tFoundFilesVector &fileList)
{
unsigned _int64 fileTime, curTime, age;
tFoundFilesVector::iterator iter;
FILETIME ftNow;
//__int64 nFileSize;
//LARGE_INTEGER li;
//li.LowPart = ftNow.dwLowDateTime;
//li.HighPart = ftNow.dwHighDateTime;
CoFileTimeNow(&ftNow);
curTime = ((_int64) ftNow.dwHighDateTime << 32) + ftNow.dwLowDateTime;
for (iter=fileList.begin(); iter<fileList.end(); iter++)
{
fileTime = ((_int64)iter->ftLastWriteTime.dwHighDateTime << 32) + iter->ftLastWriteTime.dwLowDateTime;
age = curTime - fileTime;
cout << "FILE: '" << iter->cFileName << "', AGE: " << (_int64)age/10000000UL << " seconds" << endl;
}
}
int main()
{
string fileSpec = "*.*";
tFoundFilesVector foundFiles;
tFoundFilesVector::iterator iter;
int foundCount = 0;
getFileList(L"c:\\Mapper\\*.txt", foundFiles);
getFileList(L"c:\\Mapper\\*.jpg", foundFiles);
foundCount = foundFiles.size();
if (foundCount)
{
cout << "Found "<<foundCount<<" matching files.\n";
showFileAge(foundFiles);
}
system("pause");
return 0;
}
I don't know what you've done to try to debug this but your code doesn't work at all. The reason is you're passing getFileList() a wstring but then passing that to the ANSI version of FindFirstFile(). Unless you #define UNICODE or use the appropriate compiler option, all system calls will expect char *, not UNICODE.
The easiest fix is to simply change the declaration of getFileList() to this:
int getFileList(const char * filespec, tFoundFilesVector &foundFiles)
Change the call to FindFirstFile() to this:
h = FindFirstFile((LPCSTR)filespec, &findData);
And then change the calls to it to this:
getFileList("c:\\Mapper\\*.txt", foundFiles);
getFileList("c:\\Mapper\\*.jpg", foundFiles);
Your other option is to switch all char strings to wide chars, but either way you need to be consistent throughout. Once you do that the program works as expected.
As for your final question, your program is not filtering by time at all.
Not quite an answer, but you might want to read about file system tunneling.
It may prevent you from what you're trying to do in some situations.

File Isn't Deleting

I have a code that finds files that are less than 20 seconds old. It's finding them, but I can't get them deleted. I am using remove(). I've tried using remove with wildcards but no luck. It has to be something with the syntax. Any help is appreciated. Thank you.
using namespace std;
typedef vector<WIN32_FIND_DATA> tFoundFilesVector;
std::wstring LastWriteTime;
int getFileList(const char * filespec, tFoundFilesVector &foundFiles)
{
WIN32_FIND_DATA findData;
HANDLE h;
int validResult=true;
int numFoundFiles = 0;
h = FindFirstFile((LPCSTR)filespec, &findData);
if (h == INVALID_HANDLE_VALUE)
return 0;
while (validResult)
{
numFoundFiles++;
foundFiles.push_back(findData);
validResult = FindNextFile(h, &findData);
}
return numFoundFiles;
}
void showFileAge(tFoundFilesVector &fileList)
{
unsigned _int64 fileTime, curTime, age;
tFoundFilesVector::iterator iter;
FILETIME ftNow;
CoFileTimeNow(&ftNow);
curTime = ((_int64) ftNow.dwHighDateTime << 32) + ftNow.dwLowDateTime;
for (iter=fileList.begin(); iter<fileList.end(); iter++)
{
fileTime = ((_int64)iter->ftLastWriteTime.dwHighDateTime << 32) + iter- >ftLastWriteTime.dwLowDateTime;
age = curTime - fileTime;
if (age <= (_int64)200000000UL)
{
wcout << " Delete: '" <<endl;
wcout << "FILE: '" << iter->cFileName << "', AGE: " << (_int64)age/10000000UL << " seconds" << endl;
remove("C:\\mapper\\iter->cFileName");
}
else
{
//wcout << " Quit: '" <<endl;
//return;
}
}
}
int main()
{
string fileSpec = "*.*";
tFoundFilesVector foundFiles;
tFoundFilesVector::iterator iter;
int foundCount = 0;
getFileList("c:\\Mapper\\*.txt", foundFiles);
getFileList("c:\\Mapper\\*.jpg", foundFiles);
foundCount = foundFiles.size();
if (foundCount)
{
wcout << "Found "<<foundCount<<" matching files.\n";
showFileAge(foundFiles);
}
system("pause");
return 0;
}
You need to concatenate the strings "C:\mapper\" with whatever is in iter->cFileName. The most simple way of doing that would be to use the std::string class.
The result would look something like this:
remove(string("c:\\mapper\\").append(string(iter->cFileName)).c_str());
This assumes you do not use unicode encoding of your strings, otherwise you need to use std::wstring. To use these classes you will also need to include
#include <string>
in the top of your file.

Resources