getting to an ELF file information - linux

ok...
so im suppose to write a program that prints all of the sections name in an elf file using only mmap (thats not important...)
so what i did so far is this -
maped the file into the stat structure =
map_start = mmap(0, fd_stat.st_size, PROT_READ | PROT_WRITE , MAP_SHARED, fd, 0)) <0 )
casted it into the write format from the starting point i got =
header = (Elf32_Ehdr *) map_start;
gotten the section header offset from the file =
secoff = header->e_shoff;
now - i know i need to go to the map_start+secoff location - that will give me the section table, and the sh_name will give me an index for the string table...
how to i go to the sting table?
how is it represented?
how do i use it? and is the value in sh_name the index in the string table (if it is represented as an array) , or an offset..
anyway - lets say i want to print the first two section's name - how do i do it givven the code i wrote above
help please?

header = (Elf32_Ehdr *) map_start;
secoff = header->e_shoff;
This is probably wrong. Unless the Elf32_Ehdr structure is explicitly declared __attribute__((packed)), the compiler will eventually insert padding between the members of the structure, so sizeof(Elf32_Ehdr) != (the actual size of an ELF header section). Why not simply use the libelf accessor functions instead?
Update: if you're not allowed to use accessor functions, you'll have to do something like this:
Elf32_Ehdr hdr;
memcpy(&hdr.e_ident, map_start + 0, EI_NIDENT);
memcpy(&hdr.e.type, map_start + 0 + sizeof(Elf32_half), sizeof(Elf32_Half));
et cetera.

Related

initialized string in MASM struture

In C I have this structure
struct frame
{
int whidth;
int height;
char* name;
};
I want the same in MASM
frame STRUCT
name
whidth DWORD ?
height DWORD ?
name
frame ENDS
for the name I can write ",name DWORD ?" and affect by an adress'string at runtime
but I want to initilized it.
I try this :
c1 db "big",0
c2 db "medium",0
c3 db "small",0
Frames frame <100, 50, c1>,<80, 30, c2>,<50, 20, c3>
It's not working !
I also try this
frame STRUCT
name DB <> ?
whidth DWORD ?
height DWORD ?
name
frame ENDS
don't work !
and this makes me strings of equal length filled with spaces ...
Frames frame <100, 50, "big">,<80, 30, "medium">,<50, 20, "small">
What's the right syntax?
You chose to omit some pretty important information from your question; the actual error message(s) you were getting.
The error messages I get for the DWORD ? variant are:
error A2008: syntax error : name
error A2036: too many initial values for structure
So let's look up error A2008:
syntax error :
A token at the current location caused a syntax error.
One of the following may have occurred:
A dot prefix was added to or omitted from a directive.
A reserved word (such as C or SIZE) was used as an identifier.
An instruction was used that was not available with the current processor or coprocessor selection.
A comparison run-time operator (such as ==) was used in a conditional assembly statement instead of a relational operator (such as EQ).
An instruction or directive was given too few operands.
An obsolete directive was used.
A few of these talk about directives, so let's open the list of MASM directives. Sure enough, NAME is listed as a directive. This means that you can't use NAME for your own symbols, since that falls under "A reserved word (such as C or SIZE) was used as an identifier". And because reserved words are case-insensitive that also rules out use of name for your own symbols.
So now you have two options:
Call the field something other than name.
If you don't need the NAME directive in your program you can remove its reserved word status using option nokeyword:<name>. You can then freely call your struct field name.
As far as initializing the field is concerned; the variant with DWORD ? would be the one most closely matching the C code, since only the address of the string gets stored in the struct, just like in the C code.
I found this "obvious" solution thanks for your help.
frame STRUCT
name DWORD ?
whidth DWORD ?
height DWORD ?
name
frame ENDS
c1 db "big",0
c2 db "medium",0
c3 db "small",0
Frames DWORD c1
DWORD 100
DWORD 50
DWORD c2
DWORD 80
DWORD 30
DWORD c3
DWORD 50
DWORD 20

Append to a file in the /proc file system

I'm implementing a file in /proc which I'd like to be a little more file-like than usual. In particular, I'd like to detect that someone is appending to the file and handle that correctly -- that is, I'd like to distinguish between someone doing
echo value > /proc/my_proc_file
and
echo value >> /proc/my_proc_file
Like all write functions, mine is handed an offset as its fourth argument:
ssize_t my_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *offs)
But *offs is always 0.
When I set up my proc file, I'm specifying seq_lseek as the lseek function:
struct file_operations my_proc_fops = {
.open = my_proc_open,
.read = seq_read,
.write = my_proc_write,
.llseek = seq_lseek,
};
Inspecting the source (in fs/seq_file.c), it looks like seq_lseek maintains file->f_pos appropriately, but when I look at file->f_pos in my write function, it's always 0, too. (This may not be surprising, since appending usually means opening with O_APPEND which doesn't result in any explicit calls to lseek.)
Anyway, is there a way to do this? Presumably these write functions wouldn't have been set up with offset pointer arguments if they weren't going to pass in useful, nonzero values from time to time...
first, from user perspective, file opened with O_APPEND will ALWAYS append data when you call write(), no matter where the f_pos is set by llseek(). but f_pos is still effective for read().
second, kernel framework dosn't know the file length unless it calls your llseek to find out, but that's not gonna happen because it will mess up f_pos,so kernel expect your driver, which is the only one who knows where is the true "end of the file", to act accordingly when (file->f_flags & O_APPEND) is true. basically, your driver needs to check that flag when write() is called and ignore the offs param and do the append.

fuse: Setting offsets for the filler function in readdir

I am implementing a virtual filesystem using the fuse, and need some understanding regarding the offset parameter in readdir.
Earlier we were ignoring the offset and passing 0 in the filler function, in which case the kernel should take care.
Our filesystem database, is storing: directory name, filelength, inode number and parent inode number.
How do i calculate get the offset?
Then is the offset of each components, equal to their size sorted in incremental form of their inode number? What happens is there is a directory inside a directory, is the offset in that case equal to the sum of the files inside?
Example: in case the dir listing is - a.txt b.txt c.txt
And inode number of a.txt=3, b.txt=5, c.txt=7
Offset of a.txt= directory offset
Offset of b.txt=dir offset + size of a.txt
Offset of c.txt=dir offset + size of b.txt
Is the above assumption correct?
P.S: Here are the callbacks of fuse
The selected answer is not correct
Despite the lack of upvotes on this answer, this is the correct answer. Cracking into the format of the void buffer should be discouraged, and that's the intent behind declaring such things void in C code - you shouldn't write code that assumes knowledge of the format of the data behind void pointers, use whatever API is provided properly instead.
The code below is very simple and straightforward, as it should be. No knowledge of the format of the Fuse buffer is required.
Fictitious API
This is a contrived example of what some device's API could look
like. This is not part of Fuse.
// get_some_file_names() -
// returns a struct with buffers holding the names of files.
// PARAMETERS
// * path - A path of some sort that the fictitious device groks.
// * offset - Where in the list of file names to start.
// RETURNS
// * A name_list, it has some char buffers holding the file names
// and a couple other auxiliary vars.
//
name_list *get_some_file_names(char *path, size_t offset);
Listing the files in parts
Here's a Fuse callback that can be registered with the Fuse system to
list the filenames provided by get_some_file_names(). It's arbitrarily named readdir_callback() so its purpose is obvious.
int readdir_callback( char *path,
void *buf, // This is meant to be "opaque".
fuse_fill_dir_t *filler, // filler takes care of buf.
off_t off, // Last value given to filler.
struct fuse_file_info *fi )
{
// Call the fictitious API to get a list of file names.
name_list *list = get_some_file_names(path, off);
for (int i = 0; i < list->length; i++)
{
// Feed the file names to filler() one at a time.
if (filler(buf, list->names[i], NULL, off + i + 1))
{
break; // filler() returned 1, requesting a break.
}
incr_num_files_listed(list);
}
if (all_files_listed(list))
{
return 1; // Tell Fuse we're done.
}
return 0;
}
The off (offset) value is not used by the filler function to fill its opaque buffer, buf. The off value is, however, meaningful to the callback as an offset base as it provides file names to filler(). Whatever value was last passed to filler() is what gets passed back to readdir_callback() on its next invocation. filler()
itself only cares whether the off value is 0 or not-0.
Indicating "I'm done listing!" to Fuse
To signal to the Fuse system that your readdir_callback() is done listing file names in parts (when the last of the list of names has been given to filler()), simply return 1 from it.
How off Is Used
The off, offset, parameter should be non-0 to perform the partial listings. That's its only requirement as far as filler() is concerned. If off is 0, that indicates to Fuse that you're going to do a full listing in one shot (see below).
Although filler() doesn't care what the off value is beyond it being non-0, the value can still be meaningfully used. The code above is using the index of the next item in its own file list as its value. Fuse will keep passing the last off value it received back to the read dir callback on each invocation until the listing is complete (when readdir_callback() returns 1).
Listing the files all at once
int readdir_callback( char *path,
void *buf,
fuse_fill_dir_t *filler,
off_t off,
struct fuse_file_info *fi )
{
name_list *list = get_all_file_names(path);
for (int i = 0; i < list->length; i++)
{
filler(buf, list->names[i], NULL, 0);
}
return 0;
}
Listing all the files in one shot, as above, is simpler - but not by much. Note that off is 0 for the full listing. One may wonder, 'why even bother with the first approach of reading the folder contents in parts?'
The in-parts strategy is useful where a set number of buffers for file names is allocated, and the number of files within folders may exceed this number. For instance, the implementation of name_list above may only have 8 allocated buffers (char names[8][256]). Also, buf may fill up and filler() start returning 1 if too many names are given at once. The first approach avoids this.
The offset passed to the filler function is the offset of the next item in the directory. You can have the entries in the directory in any order you want. If you don't want to return an entire directory at once, you need to use the offset to determine what gets asked for and stored. The order of items in the directory is up to you, and doesn't matter what order the names or inodes or anything else is.
Specifically, in the readdir call, you are passed an offset. You want to start calling the filler function with entries that will be at this callback or later. In the simplest case, the length of each entry is 24 bytes + strlen(name of entry), rounded up to the nearest multiple of 8 bytes. However, see the fuse source code at http://sourceforge.net/projects/fuse/ for when this might not be the case.
I have a simple example, where I have a loop (pseudo c-code) in my readdir function:
int my_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
(a bunch of prep work has been omitted)
struct stat st;
int off, nextoff=0, lenentry, i;
char namebuf[(long enough for any one name)];
for (i=0; i<NumDirectoryEntries; i++)
{
(fill st with the stat information, including inode, etc.)
(fill namebuf with the name of the directory entry)
lenentry = ((24+strlen(namebuf)+7)&~7);
off = nextoff; /* offset of this entry */
nextoff += lenentry;
/* Skip this entry if we weren't asked for it */
if (off<offset)
continue;
/* Add this to our response until we are asked to stop */
if (filler(buf, namebuf, &st, nextoff))
break;
}
/* All done because we were asked to stop or because we finished */
return 0;
}
I tested this within my own code (I had never used the offset before), and it works fine.

Making a WCHAR null terminated

I've got this
WCHAR fileName[1];
as a returned value from a function (it's a sys 32 function so I am not able to change the returned type). I need to make fileName to be null terminated so I am trying to append '\0' to it, but nothing seems to work.
Once I get a null terminated WCHAR I will need to pass it to another sys 32 function so I need it to stay as WCHAR.
Could anyone give me any suggestion please?
================================================
Thanks a lot for all your help. Looks like my problem has to do with more than missing a null terminated string.
//This works:
WCHAR szPath1[50] = L"\\Invalid2.txt.txt";
dwResult = FbwfCommitFile(szDrive, pPath1); //Successful
//This does not:
std::wstring l_fn(L"\\");
//Because Cache_detail->fileName is \Invalid2.txt.txt and I need two
l_fn.append(Cache_detail->fileName);
l_fn += L""; //To ensure null terminated
fprintf(output, "l_fn.c_str: %ls\n", l_fn.c_str()); //Prints "\\Invalid2.txt.txt"
iCommitErr = FbwfCommitFile(L"C:", (WCHAR*)l_fn.c_str()); //Unsuccessful
//Then when I do a comparison on these two they are unequal.
int iCompareResult = l_fn.compare(pPath1); // returns -1
So I need to figure out how these two ended up to be different.
Thanks a lot!
Since you mentioned fbwffindfirst/fbwffindnext in a comment, you're talking about the file name returned in FbwfCacheDetail. So from the fileNameLength field you know length for the fileName in bytes. The length of fileName in WCHAR's is fileNameLength/sizeof(WCHAR). So the simple answer is that you can set
fileName[fileNameLength/sizeof(WCHAR)+1] = L'\0'
Now this is important you need to make sure that the buffer you send for the cacheDetail parameter into fbwffindfirst/fbwffindnext is sizeof(WCHAR) bytes larger than you need, the above code snippet may run outside the bounds of your array. So for the size parameter of fbwffindfirst/fbwffindnext pass in the buffer size - sizeof(WCHAR).
For example this:
// *** Caution: This example has no error checking, nor has it been compiled ***
ULONG error;
ULONG size;
FbwfCacheDetail *cacheDetail;
// Make an intial call to find how big of a buffer we need
size = 0;
error = FbwfFindFirst(volume, NULL, &size);
if (error == ERROR_MORE_DATA) {
// Allocate more than we need
cacheDetail = (FbwfCacheDetail*)malloc(size + sizeof(WCHAR));
// Don't tell this call about the bytes we allocated for the null
error = FbwfFindFirstFile(volume, cacheDetail, &size);
cacheDetail->fileName[cacheDetail->fileNameLength/sizeof(WCHAR)+1] = L"\0";
// ... Use fileName as a null terminated string ...
// Have to free what we allocate
free(cacheDetail);
}
Of course you'll have to change a good bit to fit in with your code (plus you'll have to call fbwffindnext as well)
If you are interested in why the FbwfCacheDetail struct ends with a WCHAR[1] field, see this blog post. It's a pretty common pattern in the Windows API.
Use L'\0', not '\0'.
As each character of a WCHAR is 16-bit in size, you should perhaps append \0\0 to it, but I'm not sure if this works. By the way, WCHAR fileName[1]; is creating a WCHAR of length 1, perhaps you want something like WCHAR fileName[1024]; instead.
WCHAR fileName[1]; is an array of 1 character, so if null terminated it will contain only the null terminator L'\0'.
Which API function are you calling?
Edited
The fileName member in FbwfCacheDetail is only 1 character which is a common technique used when the length of the array is unknown and the member is the last member in a structure. As you have likely already noticed if your allocated buffer is is only sizeof (FbwfCacheDetail) long then FbwfFindFirst returns ERROR_NOT_ENOUGH_MEMORY.
So if I understand, what you desire to do it output the non NULL terminated filename using fprintf. This can be done as follows
fprintf (outputfile, L"%.*ls", cacheDetail.fileNameLength, cacheDetail.fileName);
This will print only the first fileNameLength characters of fileName.
An alternative approach would be to append a NULL terminator to the end of fileName. First you'll need to ensure that the buffer is long enough which can be done by subtracting sizeof (WCHAR) from the size argument you pass to FbwfFindFirst. So if you allocate a buffer of 1000 bytes, you'll pass 998 to FbwfFindFirst, reserving the last two bytes in the buffer for your own use. Then to add the NULL terminator and output the file name use
cacheDetail.fileName[cacheDetail.fileNameLength] = L'\0';
fprintf (outputfile, L"%ls", cacheDetail.fileName);

vc++ 6.0 serial communicaton

In vc++ i am using MScomm for serial communication,
i received data in this format 02120812550006050.0,
i am not gettng how to read this ,in which format it is,
begning starting frame and at the end ending file, remaing i dont know.
EDIT 1:
it contains date time and data how i can seperate this one
The funny characters are markers indicating things like record start, record end, field separator and so on. Without knowing the actual protocol, it's a little hard to tell.
The data is a lot easier.
Between the 000f and 0002 markers you have a date/time field, 2nd of December 2008, 12:55:00.
Between 0002 and 0003 marker, it looks like a simple float which could be a dollar value or anytrhing really, it depends on what's at the other end of the link.
To separate it, I'm assuming you've read it into a variable character array of some sort. Just look for the markers and extract the fields in between them.
The date/time is fixed size and the value probably is as well (since it has a leading 0), so you could probably just use memcpy's to pull out the information you need from the buffer, null terminate them, convert the value to a float, and voila.
If it is fixed format, you can use something like:
static void extract (char *buff, char *date, char *time, float *val) {
// format is "\x01\x0fDDMMYYhhmmss\x02vvvvvvv\x03\x04"
char temp[8];
memcpy (date, buff + 2, 6); date[6] = '\0';
memcpy (time, buff + 8, 6); time[6] = '\0';
memcpy (temp, buff + 15, 7); temp[7] = '\0';
*val = atof (temp);
}
and call it with:
char buff[26]; // must be pre-filled before calling extract()
char dt[8];
char tm[8];
float val;
extract (buffer, dt, tm, &val);
If not fixed format, you just have to write code to detect the positions of the field separators and extract what's between them.
It is unlikely that you will figure it out unless you know what you are communicating with and how it communicates with you. (hint -- you can try telling us)

Resources