consolidate all repos to one for archive

This commit is contained in:
2025-01-28 13:46:42 +01:00
commit a6610fbc7a
5350 changed files with 2705721 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
all: build run
debug: buildd run clean
zip:
zip naloga.zip main.c Makefile podatki.c podatki.h
build: main.c podatki.c podatki.h
gcc -m32 -O3 main.c podatki.c -o demo_podatki
buildd: main.c podatki.c podatki.h
gcc -g -m32 main.c podatki.c -o demo_podatki -fsanitize=address -fno-omit-frame-pointer
run:
time ./demo_podatki
clean:
rm -f demo_podatki

View File

@@ -0,0 +1,11 @@
#include <stdlib.h>
#include <stdio.h>
#include "podatki.h"
int main(){
void* pomnilnik = rezerviraj(sizeof(uint16_t)*6);
vstavi(pomnilnik);
izpis(pomnilnik);
brisi(pomnilnik);
return 0;
}

View File

@@ -0,0 +1,46 @@
#include <stdio.h>
#include <stdlib.h>
#include "podatki.h"
uint16_t* rezerviraj(int velikostZlogi){
uint16_t* ret = malloc(velikostZlogi);
for (size_t i = 0; i < velikostZlogi/sizeof(uint16_t); i++)
{
ret[i] = 26132;
}
return ret;
}
void brisi(uint16_t* pomnilnik){
free(pomnilnik);
}
uint16_t* vstavi(uint16_t* pomnilnik){
uint8_t* point = (uint8_t*)pomnilnik;
*(char*)point = 'X';
point++;
*(char*)point = 'P';
point++;
*(char*)point = 'O';
point++;
*(float*)point = (22.0/7.0);
point += 4;
*(uint32_t*)point = 26132;
point += 4;
*(char*)point = '!';
}
void izpis(uint16_t* pomnilnik){
uint8_t* point = (uint8_t*)pomnilnik;
printf("%c\n", *(char*)point);
point++;
printf("%c\n", *(char*)point);
point++;
printf("%c\n", *(char*)point);
point++;
printf("%f\n", *(float*)point);
point+=4;
printf("%d\n", *(uint32_t*)point);
point+=4;
printf("%c\n", *(char*)point);
}

View File

@@ -0,0 +1,14 @@
#ifndef PODATKI
#define PODATKI
#include <stdint.h>
uint16_t* rezerviraj(int velikostZlogi);
void brisi(uint16_t* pomnilnik);
uint16_t* vstavi(uint16_t* pomnilnik);
void izpis(uint16_t* pomnilnik);
#endif

View File

@@ -0,0 +1,18 @@
all: build run
debug: buildd run clean
zip:
zip naloga.zip main.c Makefile pretvori.c pretvori.h
build: main.c pretvori.c pretvori.h
gcc -m32 main.c pretvori.c -o demo_pretvori
buildd: main.c pretvori.c pretvori.h
gcc -g -m32 main.c pretvori.c -o demo_pretvori -fsanitize=address -fno-omit-frame-pointer
run:
./demo_pretvori 80
clean:
rm -f demo_pretvori

View File

@@ -0,0 +1,18 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "pretvori.h"
int main(int argc, char *argv[])
{
if(argc < 2) {
printf("Ni dovolj argumentov");
return -1;
}
int unicode = preberiVhod(argv);
int utf8 = pretvoriZnak(unicode);
izpisiZnak(utf8);
return 0;
}

View File

@@ -0,0 +1,90 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "pretvori.h"
int preberiVhod(char* cmd[])
{
unsigned int ret = 0;
int len = strlen(cmd[1]);
uint8_t hex = 0;
for (size_t i = 0; i < len; i++)
{
if(cmd[1][i] >= '0' && cmd[1][i] <= '9')
{
hex = cmd[1][i] - '0';
}
else if (cmd[1][i] >= 'A' && cmd[1][i] <= 'F')
{
hex = cmd[1][i] - 'A' + 10;
}
ret = ret << 4;
ret = ret | hex;
}
return ret;
}
int pretvoriZnak(int znak)
{
int ret = 0;
if(znak <= 0x7F)
{
return znak;
}
if(znak <= 0x7FF)
{
//110xxxxx10xxxxxx
ret = 0b1100000010000000;
uint32_t mask1 = 0b111111;
ret = ret | (znak & mask1);
uint32_t mask2 = 0b1111100000000;
ret = ret | ((znak << 2) & mask2);
return ret;
}
//if((znak >> 13) == 0b110)
if(znak <= 0xFFFF)
{
//1110xxxx10xxxxxx10xxxxxx
ret = 0b111000001000000010000000;
uint32_t mask1 = 0b111111;
ret = ret | (znak & mask1);
uint32_t mask2 = 0b11111100000000;
ret = ret | ((znak << 2) & mask2);
uint32_t mask3 = 0b11110000000000000000;
ret = ret | ((znak << 4) & mask3);
return ret;
}
return ret;
}
void izpisiZnak(int znak)
{
printf("UTF-8 binarno: ");
int firstZero = 0;
if ( znak <= 0xFF ) firstZero = 7;
else if (znak <= 0xFFFF ) firstZero = 15;
else if (znak <= 0xFFFFFF ) firstZero = 23;
for (int i = firstZero; i >= 0; i--)
{
// Z bitshiftanjem pogledam ali je na mestu 1 ce je dobim neko stevilo vecje od 1 in zapisem 1
int j = znak & (1 << i);
printf("%d", (j>0)?1:0);
if(i % 4 == 0) printf(" ");
}
printf("\nUTF-8 hex: %X", znak);
printf("\n");
}

View File

@@ -0,0 +1,8 @@
#ifndef PODATKI
#define PODATKI
int preberiVhod(char* cmd[]);
int pretvoriZnak(int znak);
void izpisiZnak(int znak);
#endif

View File

@@ -0,0 +1,21 @@
all: build run
debug: buildd run clean
zip:
zip naloga.zip main.c Makefile
build: main.c
gcc -m32 -O3 main.c -o demo_client
buildd: main.c
gcc -g -m32 main.c -o demo_client -fsanitize=address -fno-omit-frame-pointer
run:
./demo_client localhost 8003 test1
clean:
rm -f demo_client main
chm:
chmod 755 script.sh

View File

@@ -0,0 +1,241 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <dirent.h>
#define MAXDATASIZE 1024
#define DATOTEKA 2147483648
#define MAPA 1073741824
#define KONEC 0
typedef struct Data
{
uint32_t size;
uint32_t type;
char name[128];
} Data;
int isDir(const char *path)
{
struct stat path_stat;
stat(path, &path_stat);
return S_ISDIR(path_stat.st_mode);
}
void sendFile(int sockfd, const char *fileName)
{
struct stat st;
stat(fileName, &st);
Data dataS;
dataS.size = st.st_size;
dataS.type = DATOTEKA;
memset(dataS.name, '\0', sizeof(dataS.name));
strcpy(dataS.name, fileName);
if (send(sockfd, &dataS, sizeof(dataS), 0) < 0)
{
perror("send");
return;
}
FILE *ptr = fopen(fileName, "rb");
if (ptr == NULL)
{
perror("File");
return;
}
uint8_t buffer[MAXDATASIZE];
size_t bytesRead = 0;
while (bytesRead < st.st_size)
{
size_t read = fread(buffer, 1, sizeof(buffer), ptr);
if (send(sockfd, buffer, read, 0) < 0)
{
perror("send");
}
bytesRead += read;
}
fclose(ptr);
printf("USPEL\tZBIRKA\t%s\t%d\n", dataS.name, dataS.size);
}
void sendDir(int sockfd, const char *folderName)
{
Data dataToSend;
dataToSend.size = 0;
dataToSend.type = MAPA;
strcpy(dataToSend.name, folderName);
if (send(sockfd, &dataToSend, sizeof(dataToSend), 0) < 0)
{
perror("send");
return;
}
printf("USPEL\tIMENIK\t%s\t%d\n", dataToSend.name, dataToSend.size);
}
void reciveConferm(int sockfd)
{
uint8_t ret;
if ((recv(sockfd, &ret, sizeof(ret), 0)) == -1)
{
perror("recv");
}
}
void sendEnd(int sockfd)
{
Data dataToSend;
dataToSend.size = 0;
dataToSend.type = KONEC;
strcpy(dataToSend.name, "");
if (send(sockfd, &dataToSend, sizeof(dataToSend), 0) < 0)
{
perror("send");
return;
}
}
void sendFullFile(int sockfd, char *input)
{
//nik/nik/nik.txt
char *ptr = strtok(input, "/");
char fileName[128];
memset(fileName, '\0', sizeof(fileName));
while (ptr != NULL)
{
strcat(fileName, ptr);
if (isDir(fileName))
{
sendDir(sockfd, fileName);
strcat(fileName, "/");
}
else
{
sendFile(sockfd, fileName);
}
reciveConferm(sockfd);
ptr = strtok(NULL, "/");
}
}
void sendFullDir(int sockfd, char *input)
{
char fileName[128];
memset(fileName, '\0', sizeof(fileName));
//nik/test
char *ptr = strtok(input, "/");
while (ptr != NULL)
{
strcat(fileName, ptr);
if (isDir(fileName))
{
sendDir(sockfd, fileName);
strcat(fileName, "/");
}
reciveConferm(sockfd);
ptr = strtok(NULL, "/");
}
struct dirent *files;
DIR *dir = opendir(fileName);
if (dir == NULL)
{
printf("Directory cannot be opened!");
return;
}
//nik/test/nik.txt
char srcName[128];
while ((files = readdir(dir)) != NULL)
{
if(strncmp( "..", files->d_name, 2) > -1) continue;
if(strncmp( ".", files->d_name, 1) > -1) continue;
strcpy(srcName, fileName);
strcat(srcName, files->d_name);
if (!isDir(srcName))
{
sendFile(sockfd, srcName);
reciveConferm(sockfd);
}
else
{
sendFullDir(sockfd, srcName);
}
}
closedir(dir);
}
int main(int argc, char *argv[])
{
if (argc != 4)
{
//write(0, "Uporaba: TCPtimec ime vrata datoteka\n\0", 29);
printf("Uporaba: TCPtimec ime vrata datoteka\n");
exit(1);
}
int sockfd; // socekt file descriptor, new file descriptor
struct hostent *he; // pointer to the structure hostent (returned by gethostbyname)
struct sockaddr_in their_addr; // server address
// get the server IP address
if ((he = gethostbyname(argv[1])) == NULL)
{
herror("gethostbyname"); // prints string + value of h_error variable [HOST_NOT_FOUND || NO_ADDRESS or NO_DATA || NO_RECOVERY || TRY_AGAIN]
exit(1);
}
// create socket
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET; // family to Address Family InterNET
their_addr.sin_port = htons(atoi(argv[2])); // get server's port number - should be checked for input errors (not a number, etc.)
their_addr.sin_addr = *((struct in_addr *)he->h_addr); // server's IP address from hostent structure pointed to by he variable...
memset(&(their_addr.sin_zero), '\0', 8); // for conversion between structures only, a trick to ensure pointer casting...
// connect to the server... (no bind necessary as we are connecting to remote host... Kernel will find a free port for us and will bind it to sockfd)
if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
//nik
if (isDir(argv[3]))
{
sendFullDir(sockfd, argv[3]);
}
else
{
sendFullFile(sockfd, argv[3]);
}
sendEnd(sockfd);
// close socket
close(sockfd);
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -0,0 +1 @@
test2

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -0,0 +1,21 @@
all: build run
debug: buildd run clean
zip:
zip naloga.zip main.c Makefile
build: main.c
gcc -m32 -O3 main.c -o demo_streznik -pthread
buildd: main.c
gcc -g -m32 main.c -o demo_streznik -fsanitize=address -fno-omit-frame-pointer
run:
./demo_streznik 8003
clean:
rm -f demo_streznik
cleanAll:
rm -f img.jpg text.txt Video1.mp4 Video2.mp4

View File

@@ -0,0 +1,160 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <pthread.h>
#include <string.h>
#define MAXDATASIZE 1024
#define DATOTEKA 2
#define MAPA 1
#define KONEC 0
typedef struct Data
{
uint32_t sizeOfFile;
uint32_t type;
char fileName[128];
} Data;
void reciveFile(int newfd, Data data)
{
uint8_t buffer[MAXDATASIZE];
int numbytes = 0;
FILE *wptr = fopen(data.fileName, "wb");
size_t bytesRecived = 0;
while (bytesRecived < data.sizeOfFile)
{
if ((numbytes = recv(newfd, buffer, MAXDATASIZE, 0)) == -1)
{
perror("recv");
return;
}
fwrite(buffer, numbytes, 1, wptr);
bytesRecived += numbytes;
}
fclose(wptr);
}
void sendConf(int newfd)
{
uint8_t ret = 0;
if (send(newfd, &ret, sizeof(ret), 0) < 0)
{
perror("send1");
return;
}
}
void reciveFolder(Data data)
{
mkdir(data.fileName, 0777);
}
void *recive(void *fd)
{
int newfd = *(int *)fd;
int exit = 0;
while (1)
{
Data recivedData;
if ((recv(newfd, &recivedData, sizeof(recivedData), 0)) == -1)
{
perror("recv");
// exit(1);
}
switch (recivedData.type)
{
case DATOTEKA:
reciveFile(newfd, recivedData);
printf("USPEL\tZBIRKA\t%s\t%d\n", recivedData.fileName, recivedData.sizeOfFile);
break;
case MAPA:
reciveFolder(recivedData);
printf("USPEL\tIMENIK\t%s\t%d\n", recivedData.fileName, recivedData.sizeOfFile);
break;
case KONEC:
close(newfd);
exit = 1;
break;
default:
break;
}
if (exit)
break;
sendConf(newfd);
}
}
int main(int argc, char *argv[])
{
int sockfd; // socekt file descriptor, new file descriptor
socklen_t length; // socket length (length of clinet address)
struct sockaddr_in saddr, caddr; // server address, client address
time_t itime; // time format
char *tstr; // var holding the string to be send via TCP
if (argc != 2)
{
printf("Uporaba: demo_client vrata (vrata 0-1024 so rezervirana za jedro)\n");
exit(1);
}
// create socket
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
}
saddr.sin_family = AF_INET; // IPv4
saddr.sin_addr.s_addr = INADDR_ANY; // localhost
saddr.sin_port = htons(atoi(argv[1])); // port converted from ascii to integer
// binds the socket file description to the actual port (similar to open)
if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
{
perror("bind");
return 0;
}
// start listening on the given port
if (listen(sockfd, 0) < 0)
{
perror("listen");
return 0;
}
length = sizeof(caddr); // length of client address
pthread_t thread_id[10];
int newfd[10];
uint8_t kaz = 0;
while (1)
{
if ((newfd[kaz] = accept(sockfd, (struct sockaddr *)&caddr, &length)) < 0)
{
perror("accept");
return 0;
}
recive(newfd);
pthread_create(&thread_id[kaz], NULL, recive, &newfd[kaz]);
// recive(newfd[kaz]);
kaz++;
kaz = kaz % 10;
}
for (size_t i = 0; i < 10; i++)
{
pthread_join(thread_id[i], NULL);
}
close(sockfd);
return 0;
}

View File

@@ -0,0 +1,28 @@
all: build run
zip:
zip naloga.zip main.c Makefile
build: main.o
ld -m elf_i386 main.o \
/usr/lib32/crt1.o \
/usr/lib32/crti.o \
/usr/lib32/crtn.o \
-dynamic-linker \
/usr/lib32/ld-linux.so.2 \
-lc -o hello \
run: hello
./hello
clean:
rm -f hello main.i main.s main.o
build_i: main.c
cpp -m32 main.c -o main.i
build_s: main.i
gcc -S -m32 main.i -o main.s
build_o: main.s
as -32 main.s -o main.o

View File

@@ -0,0 +1,7 @@
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}

View File

@@ -0,0 +1,23 @@
all: build run
debug: buildd run clean
zip:
zip naloga.zip hello.c Makefile fun.c fun.h main.c
build: build_hello build_elf_changer
build_hello: hello.c
gcc -m32 hello.c -o hello
buildd: main.c fun.c
gcc -g -m32 main.c fun.c -o elf_changer -fsanitize=address -fno-omit-frame-pointer -Wall -Wextra -Wpedantic -Werror
build_elf_changer:
gcc -m32 main.c fun.c -o elf_changer -Wall -Wextra -Wpedantic -Werror
run:
./elf_changer -h hello
clean:
rm -f hello elf_changer

View File

@@ -0,0 +1,299 @@
#include "fun.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printElf(const char *fileName)
{
FILE *fp = fopen(fileName, "rb");
if (fp == NULL)
{
printf("Error: cannot open file\n");
return;
}
Elf32_Ehdr ehdr;
fread(&ehdr, sizeof(Elf32_Ehdr), 1, fp);
fclose(fp);
printf("ELF header:\n");
printf(" Magic number:\t\t\t\t\t\t%02x %02x %02x %02x\n", ehdr.e_ident[0], ehdr.e_ident[1], ehdr.e_ident[2], ehdr.e_ident[3]);
printf(" Class:\t\t\t\t\t\t");
switch (ehdr.e_ident[EI_CLASS])
{
case ELFCLASSNONE:
printf("Invalid class\n");
break;
case ELFCLASS32:
printf("ELF32\n");
break;
case ELFCLASS64:
printf("ELF64\n");
break;
default:
printf("Unknown class (0x%x)\n", ehdr.e_ident[4]);
break;
}
printf(" Data:\t\t\t\t\t\t\t");
switch (ehdr.e_ident[EI_DATA])
{
case ELFDATANONE:
printf("Invalid data encoding\n");
break;
case ELFDATA2LSB:
printf("2's complement, little endian\n");
break;
case ELFDATA2MSB:
printf("2's complement, big endian\n");
break;
default:
printf("Unknown data encoding (0x%x)\n", ehdr.e_ident[5]);
break;
}
printf(" Version:\t\t\t\t\t\t");
switch (ehdr.e_ident[EI_VERSION])
{
case EV_NONE:
printf("Invalid version\n");
break;
case EV_CURRENT:
printf("Current version\n");
break;
default:
printf("Unknown version (0x%x)\n", ehdr.e_ident[6]);
break;
}
printf(" OS/ABI:\t\t\t\t\t\t");
switch (ehdr.e_ident[EI_OSABI])
{
case ELFOSABI_NONE:
printf("UNIX System V ABI\n");
break;
default:
printf("Unknown OS/ABI (0x%x)\n", ehdr.e_ident[7]);
break;
}
printf(" ABI Version:\t\t\t\t\t\t%d\n", ehdr.e_ident[EI_ABIVERSION]);
printf(" Type:\t\t\t\t\t\t\t");
switch (ehdr.e_type)
{
case ET_NONE:
printf("No file type\n");
break;
case ET_REL:
printf("Relocatable file\n");
break;
case ET_EXEC:
printf("Executable file\n");
break;
case ET_DYN:
printf("Shared object file\n");
break;
case ET_CORE:
printf("Core file\n");
break;
case ET_LOPROC:
printf("Processor-specific\n");
break;
case ET_HIPROC:
printf("Processor-specific\n");
break;
default:
printf("Unknown type (0x%x)\n", ehdr.e_type);
break;
}
printf(" Machine:\t\t\t\t\t\t");
switch (ehdr.e_machine)
{
case EM_386:
printf("Intel 80386\n");
break;
default:
printf("Unknown type (0x%x)\n", ehdr.e_type);
break;
}
printf(" Version:\t\t\t\t\t\t0x%x\n", ehdr.e_version);
printf(" Entry point address:\t\t\t\t\t0x%x\n", ehdr.e_entry);
printf(" Start of program headers:\t\t\t\t%d (bytes into file)\n", ehdr.e_phoff);
printf(" Start of section headers:\t\t\t\t%d (bytes into file)\n", ehdr.e_shoff);
printf(" Flags:\t\t\t\t\t\t0x%x\n", ehdr.e_flags);
printf(" Size of this header:\t\t\t\t\t%d (bytes)\n", ehdr.e_ehsize);
printf(" Size of program headers:\t\t\t\t%d (bytes)\n", ehdr.e_phentsize);
printf(" Number of program headers:\t\t\t\t%d\n", ehdr.e_phnum);
printf(" Size of section headers:\t\t\t\t%d (bytes)\n", ehdr.e_shentsize);
printf(" Number of section headers:\t\t\t\t%d \n", ehdr.e_shnum);
printf(" Section header string table index:\t\t\t%d \n", ehdr.e_shstrndx);
}
void printElfFunc(const char *fileName)
{
FILE *fd = fopen(fileName, "rb");
if (!fd)
{
perror("Failed to open file");
return;
}
Elf32_Ehdr ehdr;
fread(&ehdr, sizeof(Elf32_Ehdr), 1, fd);
fseek(fd, ehdr.e_shoff, SEEK_SET);
Elf32_Shdr simbolHdr;
Elf32_Shdr stringHdr;
uint8_t strtab = 0;
for (size_t i = 0; i < ehdr.e_shnum; i++)
{
Elf32_Shdr shdr;
fread(&shdr, sizeof(Elf32_Shdr), 1, fd);
if (shdr.sh_type == SHT_SYMTAB)
{
simbolHdr = shdr;
}
else if (shdr.sh_type == SHT_STRTAB)
{
strtab++;
if (strtab == 2)
{
stringHdr = shdr;
}
}
}
size_t numOfSimbols = simbolHdr.sh_size / sizeof(Elf32_Sym);
char name[20];
memset(name, 0, sizeof(name));
printf("%-10s%-10s %-10s%-20s\n", "NR", "Value", "Size", "Name");
int pos = 0;
for (size_t i = 0; i < numOfSimbols; i++)
{
fseek(fd, simbolHdr.sh_offset + i * sizeof(Elf32_Sym), SEEK_SET);
Elf32_Sym sys;
fread(&sys, sizeof(Elf32_Sym), 1, fd);
if (sys.st_size > 50)
{
printf("%-10d", pos++);
printf("0x%-8x ", sys.st_value);
printf("%-10d", sys.st_size);
fseek(fd, stringHdr.sh_offset + sys.st_name, SEEK_SET);
fread(&name, sizeof(name), 1, fd);
printf("%-20s\n", name);
}
}
fclose(fd);
return;
}
void changeElf(int argc, const char **argv)
{
FILE *fd = fopen(argv[2], "r+b");
if (!fd)
{
perror("Failed to open file");
return;
}
Elf32_Ehdr ehdr;
fread(&ehdr, sizeof(Elf32_Ehdr), 1, fd);
fseek(fd, ehdr.e_shoff, SEEK_SET);
Elf32_Shdr simbolHdr;
Elf32_Shdr stringHdr;
uint8_t strtab = 0;
for (size_t i = 0; i < ehdr.e_shnum; i++)
{
Elf32_Shdr shdr;
fread(&shdr, sizeof(Elf32_Shdr), 1, fd);
if (shdr.sh_type == SHT_SYMTAB)
{
simbolHdr = shdr;
}
else if (shdr.sh_type == SHT_STRTAB)
{
strtab++;
if (strtab == 2)
{
stringHdr = shdr;
}
}
}
size_t numOfSimbols = simbolHdr.sh_size / sizeof(Elf32_Sym);
char name[20];
memset(name, 0, sizeof(name));
printf("%-10s\t%s\t\t%s\t%s\t\n", "IME", "NASLOV", "VREDNOST", "NOVA_VREDNOST");
for (unsigned int i = 0; i < numOfSimbols; ++i)
{
fseek(fd, simbolHdr.sh_offset + i * sizeof(Elf32_Sym), SEEK_SET);
Elf32_Sym sys;
fread(&sys, sizeof(Elf32_Sym), 1, fd);
if (!(ELF32_ST_TYPE(sys.st_info) == STT_OBJECT && ELF32_ST_BIND(sys.st_info) == STB_GLOBAL))
continue;
fseek(fd, stringHdr.sh_offset + sys.st_name, SEEK_SET);
fread(&name, sizeof(name), 1, fd);
int con = 1;
for (int j = 3; j < argc; j++)
{
if (strcmp(name, argv[j]) == 0)
{
con = 0;
break;
}
}
if (con)
continue;
printf("%-10s\t", name);
printf("%x\t\t", sys.st_value);
fseek(fd, ehdr.e_shoff + sys.st_shndx * sizeof(Elf32_Shdr), SEEK_SET);
Elf32_Shdr hdr;
fread(&hdr, sizeof(Elf32_Shdr), 1, fd);
uint32_t realAddr = (sys.st_value - hdr.sh_addr) + hdr.sh_offset;
fseek(fd, realAddr, SEEK_SET);
uint32_t val;
fread(&val, sizeof(uint32_t), 1, fd);
printf("%x\t\t", val);
val += 10;
fseek(fd, realAddr, SEEK_SET);
fwrite(&val, sizeof(val), 1, fd);
printf("%x\n", val);
}
fclose(fd);
return;
}

View File

@@ -0,0 +1,4 @@
#include <elf.h>
void printElf(const char *fileName);
void printElfFunc(const char *fileName);
void changeElf(int argc, const char **argv);

View File

@@ -0,0 +1,18 @@
#include <stdio.h>
int funkcija(int a)
{
return a + 1;
}
int g1;
int g2 = 10;
int g3 = 14;
int main()
{
printf("Vrednost g1: %d\n", g1);
printf("Vrednost g2: %d\n", g2);
printf("Vrednost g3: %d\n", g3);
return 0;
}

View File

@@ -0,0 +1,32 @@
#include <stdio.h>
#include <stdlib.h>
#include "fun.h"
int main(int argc, const char *argv[])
{
if (argc < 3)
{
printf("Usage: %s [-hcl] <elf_path> \n", argv[0]);
exit(1);
}
char var = argv[1][1];
if (var == 'h')
{
printElf(argv[2]);
}
else if (var == 'i')
{
printElfFunc(argv[2]);
}
else if (var == 'c')
{
changeElf(argc, argv);
}
else
{
printf("You entered something else\n");
}
return 0;
}

View File

@@ -0,0 +1,17 @@
all: lib build run clean
build:
gcc -m32 main.c -o demo_eksplicitno -ldl
run:
./demo_eksplicitno "Jaz Sem Velik" 2 5
clean:
rm -f demo_eksplicitno libXPO.a libXPO.o libXPO.so
lib:
gcc -m32 -c libXPO.c -o libXPO.o
gcc -m32 -shared -o libXPO.so libXPO.o
zip:
zip eksplicitno.zip Makefile libXPO.c libXPO.h main.c

View File

@@ -0,0 +1,17 @@
#include "libXPO.h"
#include <string.h>
#include <stdio.h>
uint32_t sestej(uint32_t a, uint32_t b)
{
return a+b;
}
void niz_veliki(char* niz)
{
size_t size = strlen(niz);
for (size_t i = 0; i < size; i++)
if(niz[i] >= 'a' && niz[i] <= 'z')
niz[i] -= 32;
}

View File

@@ -0,0 +1,5 @@
#include <inttypes.h>
#include <stdlib.h>
uint32_t sestej(uint32_t a, uint32_t b);
void niz_veliki(char* niz);

View File

@@ -0,0 +1,71 @@
#include <stdio.h>
#include <dlfcn.h>
#include <locale.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
if(argc < 3){
printf("Usage");
return 0;
}
char* niz = argv[1];
int i = atoi(argv[2]);
int j = atoi(argv[3]);
void* handle = NULL;
void (*izpis)();
int (*vsota)(int,int);
handle = dlopen("./libXPO.so",RTLD_LAZY);
if (handle == NULL)
{
perror("Ne morem odpreti libprva.so\n");
return -1;
}
izpis=(void(*)(void))dlsym(handle,"niz_veliki");
if (izpis==NULL)
{
perror("Ne najdem funkcije izpisi_pozdrav\n");
return -2;
}
izpis(niz);
printf("%s\n", niz);
vsota=(int(*)(int,int))dlsym(handle,"sestej");
if (vsota==NULL)
{
perror("Ne najdem funkcije sestej\n");
return -3;
}
printf("rezultat: %d\n",vsota(i,j));
dlclose(handle);
return 0;
}

View File

@@ -0,0 +1,17 @@
all: lib build run
build:
gcc -m32 main.c -o demo_implicitno -L. -lXPO
run:
./demo_implicitno "Jaz Sem Velik" 2 5
clean:
rm -f demo_implicitno libXPO.a libXPO.o libXPO.so
lib:
gcc -m32 -c libXPO.c -o libXPO.o
gcc -m32 -shared -o libXPO.so libXPO.o
zip:
zip implicitno.zip Makefile libXPO.c libXPO.h main.c

View File

@@ -0,0 +1,17 @@
#include "libXPO.h"
#include <string.h>
#include <stdio.h>
uint32_t sestej(uint32_t a, uint32_t b)
{
return a+b;
}
void niz_veliki(char* niz)
{
size_t size = strlen(niz);
for (size_t i = 0; i < size; i++)
if(niz[i] >= 'a' && niz[i] <= 'z')
niz[i] -= 32;
}

View File

@@ -0,0 +1,5 @@
#include <inttypes.h>
#include <stdlib.h>
uint32_t sestej(uint32_t a, uint32_t b);
void niz_veliki(char* niz);

View File

@@ -0,0 +1,15 @@
#include <stdio.h>
#include "libXPO.h"
//export LD_LIBRARY_PATH=.
int main(int argc, char** argv)
{
char* niz = argv[1];
int i = atoi(argv[2]);
int j = atoi(argv[3]);
niz_veliki(niz);
printf("%s\n", niz);
printf("rezultat: %d\n", sestej(i,j));
return 0;
}

View File

@@ -0,0 +1,17 @@
all: lib build run
build:
gcc -m32 main.c -o demo_staticno libXPO.a
run:
./demo_staticno "Jaz Sem Velik" 5 6
clean:
rm -f demo_staticno libXPO.a libXPO.o
lib:
gcc -m32 -c libXPO.c -o libXPO.o
ar rcs libXPO.a libXPO.o
zip:
zip staticno.zip Makefile libXPO.c libXPO.h main.c

View File

@@ -0,0 +1,17 @@
#include "libXPO.h"
#include <string.h>
#include <stdio.h>
uint32_t sestej(uint32_t a, uint32_t b)
{
return a+b;
}
void niz_veliki(char* niz)
{
size_t size = strlen(niz);
for (size_t i = 0; i < size; i++)
if(niz[i] >= 'a' && niz[i] <= 'z')
niz[i] -= 32;
}

View File

@@ -0,0 +1,5 @@
#include <inttypes.h>
#include <stdlib.h>
uint32_t sestej(uint32_t a, uint32_t b);
void niz_veliki(char* niz);

View File

@@ -0,0 +1,14 @@
#include <stdio.h>
#include "libXPO.h"
int main(int argc, char** argv)
{
char* niz = argv[1];
int i = atoi(argv[2]);
int j = atoi(argv[3]);
niz_veliki(niz);
printf("%s\n", niz);
printf("rezultat: %d\n", sestej(i,j));
return 0;
}

View File

@@ -0,0 +1,51 @@
################################################################################################################
#
# STATICNA KNJIZNICA
################################################################################################################
$ gcc -c libprva.c -o libprva.o
$ ar rcs libprva.a libprva.o
r - Insert the files member into archive (with replacement)
c - Create the archive. The specified archive is always created if it did not exist, when you request an update
s - Write an object-file index into the archive, or update an existing one
$ gcc implicitna.c -o staticna libprva.a
################################################################################################################
#
# DINAMICNA KNJIZNICA
################################################################################################################
$ gcc -c -fPIC libprva.c
$ ld -shared -soname libprva.so.1 -o libprva.so.1.0 libprva.o
$ ldconfig -v -n .
$ ln -sf libprva.so.1 libprva.so
################################################################################################################
#
# DINAMICNA KNJIZNICA IMPLICITNO POVEZOVANJE
################################################################################################################
$ gcc implicitna.c -o implicitna -L. -lprva
#Ker uporabljamo dinamične knjižnice moramo program prevesti z dodatnimi zastavicami. Uporabiti moramo zastavico -L, s katero povemo, kje naj povezovalnik išče knjižnice in zastavico -l s katero vključimo knjižnico v program.
$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
#Preden lahko program zaženemo mu moramo na nek način sporočiti, kje lahko najde dinamično knjižnico. Ponavadi se vse knjižnice nahajajo v mapi /usr/lib, /usr/local/lib oz mapah, navedenih v datoteki /etc/ld.so.conf. Knjižnice se iščejo tudi v poteh navedenih v spremenljivki LD_LIBRARY_PATH. V našem primeru bomo knjižnico imeli kar v trenutni mapi, ki jo bomo dodali v spremenljivko z ukazom:
$ ./implicitna # Sedaj lahko zaženemo program.
$ strip --strip-unneeded implicitna
################################################################################################################
#
# DINAMICNA KNJIZNICA EXPLICITNO POVEZOVANJE
################################################################################################################
$ gcc eksplicitno.c -o eksplicitna -ldl
# Da lahko prevedemo program, moramo zraven vključiti še knjižnico libdl. Pri gcc uporabimo torej še zastavico -ldl.
$ strip --strip-unneeded eksplicitna

View File

@@ -0,0 +1,18 @@
all: libprva.o
ld -shared -soname libprva.so.1 -o libprva.so.1.0 libprva.o
ldconfig -v -n .
ln -sf libprva.so.1 libprva.so
gcc implicitna.c -o implicitna -L. -lprva
gcc eksplicitno.c -o eksplicitna -ldl
libprva.o: libprva.c
gcc -c -fPIC libprva.c
clean:
rm -f libprva.o
rm -f libprva.so.1.0
rm -f libprva.so.1
rm -f libprva.so
rm -f implicitna
rm -f eksplicitna

View File

@@ -0,0 +1,5 @@
# Knjižnice
## Prevajanje in vključevanje zunanjih modulov
Za demonstracijo preverite zbirko ukazi.txt.

View File

@@ -0,0 +1,60 @@
#include <dlfcn.h>
#include <locale.h>
#include <stdio.h>
int main()
{
void* handle = NULL;
void (*izpis)();
int (*vsota)(int,int);
printf("Primer eksplicitne uporabe dinamicnih knjiznic\n");
handle = dlopen("./libprva.so",RTLD_LAZY);
if (handle == NULL)
{
perror("Ne morem odpreti libprva.so\n");
return -1;
}
/* Klic prve funkcije */
izpis=(void(*)(void))dlsym(handle,"izpisi_pozdrav");
if (izpis==NULL)
{
perror("Ne najdem funkcije izpisi_pozdrav\n");
return -2;
}
izpis();
/* Klic druge funkcije */
vsota=(int(*)(int,int))dlsym(handle,"vrni_vsoto");
if (vsota==NULL)
{
perror("Ne najdem funkcije vrni_vsota\n");
return -3;
}
printf("Vsota: %d\n",vsota(40,2));
/* Klic tretje funkcije */
void (*izpisi_niz)(char*);
izpisi_niz=(void(*)(char*))dlsym(handle,"izpisi_niz");
if (izpisi_niz==NULL)
{
perror("Ne najdem funkcije izpisi_niz\n");
return -7;
}
izpisi_niz("Niz, ki ga izpise 3. funkcija!");
/* Spremenljivka */
int *spremenljivka;
spremenljivka=(int *)dlsym(handle,"vrednost");
if (spremenljivka==NULL)
{
perror("Ne najdem spremenljivke vrednost\n");
return -7;
}
printf("Spremenljivka ima vrednost: %d\n",*spremenljivka);
dlclose(handle);
return 0;
}

View File

@@ -0,0 +1,20 @@
#include <stdio.h>
#include "libprva.h"
int main()
{
char *niz="Niz iz glavnega programa\0";
printf("-----Zacetek-----\n");
izpisi_pozdrav();
printf("-----------------\n");
vrednost=42;
kazalec=(int *)niz;
izpisi_pozdrav();
printf("-----------------\n");
int v=vrni_vsoto(2,3);
printf("Vrnjena vsota je %d\n", v);
printf("-----------------\n");
izpisi_niz(niz);
printf("-------Konec-----\n");
return 0;
}

View File

@@ -0,0 +1,29 @@
#include <stdio.h>
/* Primer spremenljivke*/
int vrednost=999;
/* Primer kazalca */
int* kazalec;
/* Primer funkcije brez parametrov */
void izpisi_pozdrav()
{
printf("Pozdrav iz dinamicne knjiznice.\n");
printf("Spremenljivka vrednost je: %d\n ",vrednost);
printf("Kazalec kaze na naslov: %p\n",kazalec);
}
/* Primer funkcije z enim vhodnim in dvema vhodnima parametroma*/
int vrni_vsoto(int a, int b)
{
printf("Vsota je %d\n",a+b);
return a+b;
}
/* Primer funkcije, ki ima kot vhod kazalec na niz (zero terminated)*/
void izpisi_niz(char* niz)
{
printf("Vhodni niz: %s\n",niz);
}

View File

@@ -0,0 +1,9 @@
/* Prototipi funkcij in spremenljivk */
extern int vrednost;
extern int* kazalec;
void izpisi_pozdrav();
int vrni_vsoto(int a, int b);
void izpisi_niz(char* niz);

View File

@@ -0,0 +1,529 @@
################################################################################################################
#
# STATICNA KNJIZNICA
################################################################################################################
$ gcc -c libprva.c -o libprva.o
$ ar rcs libprva.a libprva.o
r - Insert the files member into archive (with replacement)
c - Create the archive. The specified archive is always created if it did not exist, when you request an update
s - Write an object-file index into the archive, or update an existing one
$ gcc implicitna.c -o staticna libprva.a
$ readelf -h libprva.a # izpise zaglavje formata ELF od knjižnice
" ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 592 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 13
Section header string table index: 10
"
$ readelf -h ./staticna # izpise zaglavje formata ELF od izvedljivega modula
" ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400460
Start of program headers: 64 (bytes into file)
Start of section headers: 6320 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 37
Section header string table index: 34
"
$ readelf -S -W libprva.a # izpise vse sekcije
" There are 13 section headers, starting at offset 0x250:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000040 00008c 00 AX 0 0 4
[ 2] .rela.text RELA 0000000000000000 000760 000120 18 11 1 8
[ 3] .data PROGBITS 0000000000000000 0000cc 000004 00 WA 0 0 4
[ 4] .bss NOBITS 0000000000000000 0000d0 000000 00 WA 0 0 4
[ 5] .rodata PROGBITS 0000000000000000 0000d0 000079 00 A 0 0 8
[ 6] .eh_frame PROGBITS 0000000000000000 000150 000078 00 A 0 0 8
[ 7] .rela.eh_frame RELA 0000000000000000 000880 000048 18 11 6 8
[ 8] .comment PROGBITS 0000000000000000 0001c8 000024 00 0 0 1
[ 9] .note.GNU-stack PROGBITS 0000000000000000 0001ec 000000 00 0 0 1
[10] .shstrtab STRTAB 0000000000000000 0001ec 000061 00 0 0 1
[11] .symtab SYMTAB 0000000000000000 000590 000180 18 12 9 8
[12] .strtab STRTAB 0000000000000000 000710 00004d 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
"
$ readelf -s libprva.a # izpise simbolno tabelo knjiznice
" File: libprva.a(libprva.o)
Symbol table '.symtab' contains 16 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS libprva.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 9
8: 0000000000000000 0 SECTION LOCAL DEFAULT 8
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 vrednost
10: 0000000000000000 59 FUNC GLOBAL DEFAULT 1 izpisi_pozdrav
11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf
13: 0000000000000008 8 OBJECT GLOBAL DEFAULT COM kazalec
14: 000000000000003b 48 FUNC GLOBAL DEFAULT 1 vrni_vsoto
15: 000000000000006b 33 FUNC GLOBAL DEFAULT 1 izpisi_niz
"
$ readelf -r libprva.a # izpise relokacijske tabele knjiznice
"
Relocation section '.rela.text' at offset 0x760 contains 12 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000005 00050000000a R_X86_64_32 0000000000000000 .rodata + 0
00000000000a 000b00000002 R_X86_64_PC32 0000000000000000 puts + fffffffffffffffc
000000000010 000900000002 R_X86_64_PC32 0000000000000000 vrednost + fffffffffffffffc
000000000015 00050000000a R_X86_64_32 0000000000000000 .rodata + 20
00000000001f 000c00000002 R_X86_64_PC32 0000000000000000 printf + fffffffffffffffc
000000000026 000d00000002 R_X86_64_PC32 0000000000000008 kazalec + fffffffffffffffc
00000000002b 00050000000a R_X86_64_32 0000000000000000 .rodata + 40
000000000035 000c00000002 R_X86_64_PC32 0000000000000000 printf + fffffffffffffffc
000000000053 00050000000a R_X86_64_32 0000000000000000 .rodata + 5c
00000000005d 000c00000002 R_X86_64_PC32 0000000000000000 printf + fffffffffffffffc
00000000007c 00050000000a R_X86_64_32 0000000000000000 .rodata + 69
000000000086 000c00000002 R_X86_64_PC32 0000000000000000 printf + fffffffffffffffc
Relocation section '.rela.eh_frame' at offset 0x880 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000020 00020000000a R_X86_64_32 0000000000000000 .text + 0
000000000040 00020000000a R_X86_64_32 0000000000000000 .text + 3b
000000000060 00020000000a R_X86_64_32 0000000000000000 .text + 6b
"
Offset . odmik od zacetka sekcije do mesta prenaslavljanja
Info - vstop v simbolno tabelo in tip prenaslavljanja
Sym.Value - vrednost simbola v simbolni tabeli
Sym.Name -ime simbola v simboni tabeli
$ readelf -s ./staticna # izpise simbolno tabelo izvedljivega modula
"
Symbol table '.dynsym' contains...
"
$ readelf -r ./staticna # izpise relokacijske tabele izvedljivega modula
"
Relocation section '.rela.dyn' at offset 0x3a8 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600fe0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
Relocation section '.rela.plt' at offset 0x3c0 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000601000 000100000007 R_X86_64_JUMP_SLO 0000000000000000 printf + 0
000000601008 000300000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000601010 000400000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
"
Offset . odmik od zacetka sekcije do mesta prenaslavljanja
Info - vstop v simbolno tabelo in tip prenaslavljanja
Sym.Value - vrednost simbola v simbolni tabeli
Sym.Name -ime simbola v simboni tabeli
$ strip --strip-unneeded staticna # odstranimo vse nepotrebne simbole
$ readelf -s ./staticna # izpisemo simbolno tabelo
"
Symbol table '.dynsym' contains 5 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
"
################################################################################################################
#
# DINAMICNA KNJIZNICA
################################################################################################################
#Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts (the dynamic loader is not part of GCC; it is part of the operating system).
$ gcc -c -fPIC libprva.c
$ readelf -r libprva.o # izpise relokacijske tabele izvedljivega modula
"
Relocation section '.rela.text' at offset 0x7a0 contains 12 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000007 000500000002 R_X86_64_PC32 0000000000000000 .rodata + fffffffffffffffc
00000000000c 000c00000004 R_X86_64_PLT32 0000000000000000 puts + fffffffffffffffc
000000000013 000900000009 R_X86_64_GOTPCREL 0000000000000000 vrednost + fffffffffffffffc
00000000001c 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 1c
000000000026 000d00000004 R_X86_64_PLT32 0000000000000000 printf + fffffffffffffffc
00000000002d 000e00000009 R_X86_64_GOTPCREL 0000000000000008 kazalec + fffffffffffffffc
000000000037 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 3c
000000000041 000d00000004 R_X86_64_PLT32 0000000000000000 printf + fffffffffffffffc
000000000061 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 58
00000000006b 000d00000004 R_X86_64_PLT32 0000000000000000 printf + fffffffffffffffc
00000000008c 000500000002 R_X86_64_PC32 0000000000000000 .rodata + 65
000000000096 000d00000004 R_X86_64_PLT32 0000000000000000 printf + fffffffffffffffc
Relocation section '.rela.eh_frame' at offset 0x8c0 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0
000000000040 000200000002 R_X86_64_PC32 0000000000000000 .text + 47
000000000060 000200000002 R_X86_64_PC32 0000000000000000 .text + 79
"
#Primerjaj z $ readelf -r libprva.a
$ ld -shared -soname libprva.so.1 -o libprva.so.1.0 libprva.o
# Z zastavico -shared povemo, da se mora modul pred izvajanjem povezal še z drugimi moduli (torej nima vstopne točke), z zastavico -soname ime_datoteke.so.verzija_vmesnika pa povemo, katera verzija vmesnika je implementirana. Vedno ko spremenimo vmesnik knjižnice, moramo spremeniti tudi to verzijo, saj se na ta način izognemo težavam z nekompatibilnimi knjižnicami. Vidimo, da ima tudi izhodni modul na koncu dve številki. Prva pove številko vmesnika, druga pa njegovo verzijo.
$ ldconfig -v -n .
" .:
libprva.so.1 -> libprva.so.1.0 (changed)
"
#Dobili smo knjižnico, ki jo moramo sedaj še namestiti. V kolikor jo želimo dani na voljo vsem, jo kopiramo v mapo /usr/lib ali /lib, v našem primeru pa jo bomo pustili kar v trenutni mapi. V vsakem primeru pa moramo pognati ukaz ldconfig, ki poišče zadnjo verzijo vsake knjižnice. V našem primeru smo napisali ukaz, ki bo iskal nove verzije samo v trenutni mapi.
# zastavice
# -v --verbose
# Verbose mode. Print current version number, the name of each directory as it is scanned and any links that are
# created.
# -n Only process directories specified on the command line. Dont process the trusted directories (/usr/lib and
# /lib) nor those specified in /etc/ld.so.conf. Implies -N.
$ ls -all
# Sedaj je ustvarjena nova povezava z imenom libprva.so.1, ki kaže na libprva.so.1.0. Ukaz "ldconfig -v -n ." torej poskrbi, da nam ni potrebno skrbeti za podverzijo knjižnice.
$ ln -sf libprva.so.1 libprva.so
# Na koncu lahko naredimo še simbolično povezavo do te knjižnice (man ln)
$ ls -all
# bodite pozorni na simbolično povezavo libprva.so -> libprva.so.1
$ readelf -h libprva.so
" ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x380
Start of program headers: 64 (bytes into file)
Start of section headers: 1840 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 4
Size of section headers: 64 (bytes)
Number of section headers: 19
Section header string table index: 16
"
$ readelf -s libprva.so
"Symbol table '.dynsym' contains 12 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000380 0 SECTION LOCAL DEFAULT 7
2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf
3: 0000000000000380 71 FUNC GLOBAL DEFAULT 7 izpisi_pozdrav
4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
5: 0000000000200688 8 OBJECT GLOBAL DEFAULT 14 kazalec
6: 00000000000003f9 35 FUNC GLOBAL DEFAULT 7 izpisi_niz
7: 00000000000003c7 50 FUNC GLOBAL DEFAULT 7 vrni_vsoto
8: 0000000000200684 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
9: 0000000000200684 0 NOTYPE GLOBAL DEFAULT ABS _edata
10: 0000000000200690 0 NOTYPE GLOBAL DEFAULT ABS _end
11: 0000000000200680 4 OBJECT GLOBAL DEFAULT 13 vrednost
Symbol table '.symtab' contains 29 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
...
16: 0000000000000000 0 FILE LOCAL DEFAULT ABS libprva.c
17: 0000000000200518 0 OBJECT LOCAL HIDDEN ABS _DYNAMIC
18: 0000000000200658 0 OBJECT LOCAL HIDDEN ABS _GLOBAL_OFFSET_TABLE_
19: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf
20: 0000000000000380 71 FUNC GLOBAL DEFAULT 7 izpisi_pozdrav
21: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
22: 0000000000200688 8 OBJECT GLOBAL DEFAULT 14 kazalec
23: 00000000000003f9 35 FUNC GLOBAL DEFAULT 7 izpisi_niz
24: 00000000000003c7 50 FUNC GLOBAL DEFAULT 7 vrni_vsoto
25: 0000000000200684 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
26: 0000000000200684 0 NOTYPE GLOBAL DEFAULT ABS _edata
27: 0000000000200690 0 NOTYPE GLOBAL DEFAULT ABS _end
28: 0000000000200680 4 OBJECT GLOBAL DEFAULT 13 vrednost
"
# Simbolna tabela .symtab podvaja vrednosti dinamične simbolne tabele .dynsym
#Primerjaj z $ readelf -s libprva.a
$ readelf -r libprva.so
"
Relocation section '.rela.dyn' at offset 0x2f0 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000200648 000500000006 R_X86_64_GLOB_DAT 0000000000200688 kazalec + 0
000000200650 000b00000006 R_X86_64_GLOB_DAT 0000000000200680 vrednost + 0
Relocation section '.rela.plt' at offset 0x320 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000200670 000200000007 R_X86_64_JUMP_SLO 0000000000000000 printf + 0
000000200678 000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
"
$ readelf -SW libprva.so # izpisemo vse sekcije
" There are 19 section headers, starting at offset 0x730:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .hash HASH 0000000000000120 000120 000044 04 A 2 0 8
[ 2] .dynsym DYNSYM 0000000000000168 000168 000120 18 A 3 2 8
[ 3] .dynstr STRTAB 0000000000000288 000288 000068 00 A 0 0 1
[ 4] .rela.dyn RELA 00000000000002f0 0002f0 000030 18 A 2 0 8
[ 5] .rela.plt RELA 0000000000000320 000320 000030 18 A 2 6 8
[ 6] .plt PROGBITS 0000000000000350 000350 000030 10 AX 0 0 4
[ 7] .text PROGBITS 0000000000000380 000380 00009c 00 AX 0 0 4
[ 8] .rodata PROGBITS 0000000000000420 000420 000079 00 A 0 0 8
[ 9] .eh_frame PROGBITS 00000000000004a0 0004a0 000078 00 A 0 0 8
[10] .dynamic DYNAMIC 0000000000200518 000518 000130 10 WA 3 0 8
[11] .got PROGBITS 0000000000200648 000648 000010 08 WA 0 0 8
[12] .got.plt PROGBITS 0000000000200658 000658 000028 08 WA 0 0 8
[13] .data PROGBITS 0000000000200680 000680 000004 00 WA 0 0 4
[14] .bss NOBITS 0000000000200688 000684 000008 00 WA 0 0 8
[15] .comment PROGBITS 0000000000000000 000684 000024 00 0 0 1
[16] .shstrtab STRTAB 0000000000000000 0006a8 000088 00 0 0 1
[17] .symtab SYMTAB 0000000000000000 000bf0 0002b8 18 18 19 8
[18] .strtab STRTAB 0000000000000000 000ea8 000084 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
"
$ objdump -d -j .plt libprva.so # izpišemo vsebino sekcije plt (Procedure Linkage Table)
"
libprva.so: file format elf64-x86-64
Disassembly of section .plt:
0000000000000350 <printf@plt-0x10>:
350: ff 35 0a 03 20 00 pushq 0x20030a(%rip) # 200660 <_GLOBAL_OFFSET_TABLE_+0x8>
356: ff 25 0c 03 20 00 jmpq *0x20030c(%rip) # 200668 <_GLOBAL_OFFSET_TABLE_+0x10>
35c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000000360 <printf@plt>:
360: ff 25 0a 03 20 00 jmpq *0x20030a(%rip) # 200670 <_GLOBAL_OFFSET_TABLE_+0x18>
366: 68 00 00 00 00 pushq $0x0
36b: e9 e0 ff ff ff jmpq 350 <printf@plt-0x10>
0000000000000370 <puts@plt>:
370: ff 25 02 03 20 00 jmpq *0x200302(%rip) # 200678 <_GLOBAL_OFFSET_TABLE_+0x20>
376: 68 01 00 00 00 pushq $0x1
37b: e9 d0 ff ff ff jmpq 350 <printf@plt-0x10>
"
# za razlago delovanje tabele plt glej slikovni material na sistemu za vaje
$ objdump -s libprva.so | grep -A 2 got
"
Contents of section .got:
200648 00000000 00000000 00000000 00000000 ................
Contents of section .got.plt:
200658 18052000 00000000 00000000 00000000 .. .............
200668 00000000 00000000 66030000 00000000 ........f.......
"
$ readelf -I libprva.so
"
Histogram for bucket list length (total of 3 buckets):
Length Number % of total Coverage
0 0 ( 0.0%)
1 1 ( 33.3%) 10.0%
2 1 ( 33.3%) 30.0%
3 0 ( 0.0%) 30.0%
4 0 ( 0.0%) 30.0%
5 0 ( 0.0%) 30.0%
6 0 ( 0.0%) 30.0%
7 1 ( 33.3%) 100.0%
"
# 3 buckets - trije vstopi v hash tabelo
# length - dolžina verige (chain) v hash tabeli
# number - število vstopov v hash tabelo s specificirano dolžino verige
# še malo večji primer .so knjižnice
$ readelf -I /lib/libc.so.6
" Histogram for bucket list length (total of 1017 buckets):
Length Number % of total Coverage
0 116 ( 11.4%)
1 268 ( 26.4%) 12.7%
2 283 ( 27.8%) 39.4%
3 194 ( 19.1%) 66.9%
4 100 ( 9.8%) 85.8%
5 40 ( 3.9%) 95.3%
6 12 ( 1.2%) 98.7%
7 4 ( 0.4%) 100.0%
"
$ sudo apt-get install elfutils # eu-readelf pove še povprečno število iskanj v hash tabeli...
$ eu-readelf -I libprva.so
"
Histogram for bucket list length in section [ 1] '.hash' (total of 3 buckets):
Addr: 0x0000000000000120 Offset: 0x000120 Link to section: [ 2] '.dynsym'
Length Number % of total Coverage
0 0 0.0%
1 1 33.3% 10.0%
2 1 33.3% 30.0%
3 0 0.0% 30.0%
4 0 0.0% 30.0%
5 0 0.0% 30.0%
6 0 0.0% 30.0%
7 1 33.3% 100.0%
Average number of tests: successful lookup: 3.200000
unsuccessful lookup: 3.333333
"
$ eu-readelf -I /lib/libc.so.6
################################################################################################################
#
# DINAMICNA KNJIZNICA IMPLICITNO POVEZOVANJE
################################################################################################################
$ gcc implicitna.c -o implicitna -L. -lprva
#Ker uporabljamo dinamične knjižnice moramo program prevesti z dodatnimi zastavicami. Uporabiti moramo zastavico -L, s katero povemo, kje naj povezovalnik išče knjižnice in zastavico -l s katero vključimo knjižnico v program.
$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
#Preden lahko program zaženemo mu moramo na nek način sporočiti, kje lahko najde dinamično knjižnico. Ponavadi se vse knjižnice nahajajo v mapi /usr/lib, /usr/local/lib oz mapah, navedenih v datoteki /etc/ld.so.conf. Knjižnice se iščejo tudi v poteh navedenih v spremenljivki LD_LIBRARY_PATH. V našem primeru bomo knjižnico imeli kar v trenutni mapi, ki jo bomo dodali v spremenljivko z ukazom:
$ ./implicitna # Sedaj lahko zaženemo program.
$ readelf -h ./implicitna
" ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400670
Start of program headers: 64 (bytes into file)
Start of section headers: 6304 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 37
Section header string table index: 34
"
$ readelf -s ./implicitna
"
Symbol table '.dynsym' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND vrni_vsoto
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND izpisi_niz
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND izpisi_pozdrav
8: 0000000000601060 0 NOTYPE GLOBAL DEFAULT ABS _end
9: 0000000000601040 0 NOTYPE GLOBAL DEFAULT ABS _edata
10: 0000000000601040 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
11: 0000000000601040 4 OBJECT GLOBAL DEFAULT 25 vrednost
12: 0000000000601048 8 OBJECT GLOBAL DEFAULT 25 kazalec
"
# primirjaj z $ readelf -s ./staticna
$ readelf -r ./implicitna
"
Relocation section '.rela.dyn' at offset 0x510 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600fe0 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000601040 000b00000005 R_X86_64_COPY 0000000000601040 vrednost + 0
000000601048 000c00000005 R_X86_64_COPY 0000000000601048 kazalec + 0
Relocation section '.rela.plt' at offset 0x558 contains 6 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000601000 000100000007 R_X86_64_JUMP_SLO 0000000000000000 printf + 0
000000601008 000200000007 R_X86_64_JUMP_SLO 0000000000000000 vrni_vsoto + 0
000000601010 000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000601018 000500000007 R_X86_64_JUMP_SLO 0000000000000000 izpisi_niz + 0
000000601020 000600000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
000000601028 000700000007 R_X86_64_JUMP_SLO 0000000000000000 izpisi_pozdrav + 0
"
# primerjaj z $ readelf -r ./staticna
$ strip --strip-unneeded implicitna
$ readelf -s ./implicitna
################################################################################################################
#
# DINAMICNA KNJIZNICA EXPLICITNO POVEZOVANJE
################################################################################################################
$ gcc eksplicitno.c -o eksplicitna -ldl
# Da lahko prevedemo program, moramo zraven vključiti še knjižnico libdl. Pri gcc uporabimo torej še zastavico -ldl.
$ readelf -h ./eksplicitna
"
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400600
Start of program headers: 64 (bytes into file)
Start of section headers: 6320 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 37
Section header string table index: 34
"
$ readelf -s ./eksplicitna
"
...
"
$ readelf -r ./eksplicitna
" Relocation section '.rela.dyn' at offset 0x4a0 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000600fe0 000200000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
Relocation section '.rela.plt' at offset 0x4b8 contains 7 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000601000 000100000007 R_X86_64_JUMP_SLO 0000000000000000 printf + 0
000000601008 000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000601010 000500000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
000000601018 000600000007 R_X86_64_JUMP_SLO 0000000000000000 dlclose + 0
000000601020 000700000007 R_X86_64_JUMP_SLO 0000000000000000 dlopen + 0
000000601028 000800000007 R_X86_64_JUMP_SLO 0000000000000000 dlsym + 0
000000601030 000900000007 R_X86_64_JUMP_SLO 0000000000000000 perror + 0
"
# primerjaj z $ readelf -r ./staticna
# primerjaj z $ readelf -r ./implicitna
$ strip --strip-unneeded eksplicitna
$ readelf -s ./eksplicitna

View File

@@ -0,0 +1,29 @@
obj-m += xpo_modul.o
all: build
build:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
load:
sudo insmod xpo_modul.ko
unload:
sudo rmmod xpo_modul
list:
sudo lsmod | grep xpo
msg:
sudo dmesg | grep xpo
start:
sudo watch -n 0.2 "cat /dev/xpo_modul"
restart: msg unload build load
zip:
zip naloga.zip Makefile xpo_modul.c xpo_modul.h

View File

@@ -0,0 +1,116 @@
#include <linux/atomic.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h> /* for sprintf() */
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/types.h>
#include"xpo_modul.h"
MODULE_AUTHOR("NIKOLA");
MODULE_DESCRIPTION("Simple kernel driver skeleton");
MODULE_LICENSE("GPL");
static int major; // major number of device driver
#define DEVICE_NAME "xpo_modul"
static struct class *cls;
static int __init xpo_driver_init(void)
{
pr_info("xpo: driver INIT\n");
major = register_chrdev(0, DEVICE_NAME, &xpo_fops);
if (major < 0) {
pr_alert("xpo: registering char device failed with %d\n", major);
return major;
} else {
pr_info("xpo: registering char device %d\n", major);
}
cls = class_create(THIS_MODULE, DEVICE_NAME);
device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
pr_info("xpo: Device created on /dev/%s\n", DEVICE_NAME);
return 0;
}
static void xpo_driver_exit(void)
{
pr_info("xpo: driver EXIT\n");
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
unregister_chrdev(major, DEVICE_NAME);
return ;
}
module_init(xpo_driver_init);
module_exit(xpo_driver_exit);
// abcdefghijklmnopqrstuvwxyz
static unsigned char xpo_map[256] =
{
[0 ... 255] = 0,
[2] = '1',
[3] = '2',
[4] = '3',
[5] = '4',
[6] = '5',
[7] = '6',
[8] = '7',
[9] = '8',
[10] = '9',
[11] = '0',
[16] = 'q',
[17] = 'w',
[18] = 'e',
[19] = 'r',
[20] = 't',
[21] = 'z',
[22] = 'u',
[23] = 'i',
[24] = 'o',
[25] = 'p',
[30] = 'a',
[31] = 's',
[32] = 'd',
[33] = 'f',
[34] = 'g',
[35] = 'h',
[36] = 'j',
[37] = 'k',
[37] = 'l',
[44] = 'y',
[45] = 'x',
[46] = 'c',
[47] = 'v',
[48] = 'b',
[49] = 'n',
[50] = 'm'
};
ssize_t xpo_read(struct file *filep, char *buff, size_t count, loff_t *offp )
{
unsigned char c = inb(0x60); // 0x60 - which key down
char buf[20];
sprintf(buf, "%u - znak: %c", c, xpo_map[c]);
printk("xpo - signal: %s\n", buf);
return 0;
}

View File

@@ -0,0 +1,20 @@
#ifndef _MY_DEVICE_H
#define _MY_DEVICE_H
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <asm/current.h>
#include <asm/segment.h>
#include <linux/uaccess.h>
#include <asm/io.h>
ssize_t xpo_read(struct file *filep, char *buff, size_t count, loff_t *offp );
struct file_operations xpo_fops={
read: xpo_read,
};
#endif

View File

@@ -0,0 +1,27 @@
obj-m += xpo_xor_module.o
all: build
build:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
load:
sudo insmod xpo_xor_module.ko
unload:
sudo rmmod xpo_xor_module
read:
sudo cat /dev/xpo_xor_module
write1:
sudo echo "NikolaJeVelik" > /dev/xpo_xor_module
write2:
sudo echo "1234567890NikolaJeVelokMozKiHodiNaFaksInJeVMariboruInSedajDelaNalogoSajmujedolgcajtinbirajepocelkajdrugega" > /dev/xpo_xor_module
zip:
zip naloga.zip Makefile xpo_xor_module.c xpo_xor_module.h

View File

@@ -0,0 +1,170 @@
/*
* xpo_xor_module.c: Creates a read-only char device that says how many times
* you have read from the dev file
*/
#include "xpo_xor_module.h"
/* Prototypes - this would normally go in a .h file */
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char __user *, size_t, loff_t *);
#define SUCCESS 0
#define DEVICE_NAME "xpo_xor_module" /* Dev name as it appears in /proc/devices */
#define BUF_LEN 80 /* Max length of the message from the device */
/* Global variables are declared as static, so are global within the file. */
static int major; /* major number assigned to our device driver */
enum {
CDEV_NOT_USED = 0,
CDEV_EXCLUSIVE_OPEN = 1,
};
/* Is device open? Used to prevent multiple access to device */
static atomic_t already_open = ATOMIC_INIT(CDEV_NOT_USED);
static char message[BUF_LEN + 1]; /* The message the device will give when asked */
static struct class *cls;
static int __init xpo_xor_module_init(void)
{
major = register_chrdev(0, DEVICE_NAME, &xpo_xor_module_fops);
if (major < 0) {
pr_alert("Registering char device failed with %d\n", major);
return major;
}
pr_info("I was assigned major number %d.\n", major);
cls = class_create(THIS_MODULE, DEVICE_NAME);
device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
sprintf(message, "I already told you %d times Hello world!\n", 1);
pr_info("Device created on /dev/%s\n", DEVICE_NAME);
return SUCCESS;
}
static void __exit xpo_xor_module_exit(void)
{
device_destroy(cls, MKDEV(major, 0));
class_destroy(cls);
/* Unregister the device */
unregister_chrdev(major, DEVICE_NAME);
}
/* Methods */
/* Called when a process tries to open the device file, like
* "sudo cat /dev/xpo_xor_module"
*/
static int device_open(struct inode *inode, struct file *file)
{
if (atomic_cmpxchg(&already_open, CDEV_NOT_USED, CDEV_EXCLUSIVE_OPEN))
return -EBUSY;
try_module_get(THIS_MODULE);
return SUCCESS;
}
/* Called when a process closes the device file. */
static int device_release(struct inode *inode, struct file *file)
{
/* We're now ready for our next caller */
atomic_set(&already_open, CDEV_NOT_USED);
/* Decrement the usage count, or else once you opened the file, you will
* never get rid of the module.
*/
module_put(THIS_MODULE);
return SUCCESS;
}
/* Called when a process, which already opened the dev file, attempts to
* read from it.
*/
static ssize_t device_read(struct file *filp,
char __user *buffer, /* buffer to fill with data */
size_t length, /* length of the buffer */
loff_t *offset)
{
/* Number of bytes actually written to the buffer */
int bytes_read = 0;
const char *message_ptr = message;
if (!*(message_ptr + *offset)) { /* we are at the end of message */
*offset = 0; /* reset the offset */
return 0; /* signify end of file */
}
message_ptr += *offset;
/* Actually put the data into the buffer */
while (length && *message_ptr) {
/* The buffer is in the user data segment, not the kernel
* segment so "*" assignment won't work. We have to use
* put_user which copies data from the kernel data segment to
* the user data segment.
*/
put_user(*(message_ptr++), buffer++);
length--;
bytes_read++;
}
*offset += bytes_read;
/* Most read functions return the number of bytes put into the buffer. */
return bytes_read;
}
static int xpo_msg_location = 0;
static uint8_t xpo_key[5] = {2,6,1,3,2};
static uint8_t xpo_key_location = 0;
static ssize_t device_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
{
int i;
for (i = 0; i < length; i++)
{
get_user(message[xpo_msg_location], buffer + i);
message[xpo_msg_location] ^= xpo_key[xpo_key_location];
xpo_key_location++;
if(xpo_key_location > 5) xpo_key_location = 0;
xpo_msg_location++;
if(xpo_msg_location > BUF_LEN - 1) xpo_msg_location = 0;
}
return i;
}
module_init(xpo_xor_module_init);
module_exit(xpo_xor_module_exit);
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,30 @@
#ifndef _MY_DEVICE_H
#define _MY_DEVICE_H
#include <linux/atomic.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h> /* for sprintf() */
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/types.h>
#include <linux/uaccess.h> /* for get_user and put_user */
#include <asm/errno.h>
static int device_open(struct inode *, struct file *);
static int device_release(struct inode *, struct file *);
static ssize_t device_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t device_write(struct file *, const char __user *, size_t, loff_t *);
static struct file_operations xpo_xor_module_fops = {
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release,
};
#endif