How does debugger know the local variables' name? - c

I begin to learn compiler.
I know that .symtab in ELF stores information about global variables and functions, but I don't find any valid information about local variables. For those local variables that are allocated on the stack, how could a debugger know their name? Are there any helpful information in ELF?
For example, here is a stupid C code:
void printLocal(){
char c1_loc='a';
int i_loc=1;
char c2_loc='b';
double d_loc=2;
char c3_loc='c';
float f_loc=3;
char c4_loc='d';
short s_loc=4;
printf("&c1_loc = %p\n",&c1_loc);
printf("&i_loc = %p\n",&i_loc);
printf("&c2_loc = %p\n",&c2_loc);
printf("&d_loc = %p\n",&d_loc);
printf("&c3_loc = %p\n",&c3_loc);
printf("&f_loc = %p\n",&f_loc);
printf("&c4_loc = %p\n",&c4_loc);
printf("&s_loc = %p\n",&s_loc);
}
And I get the .debug_info in ELF :
<1><490>: Abbrev Number: 19 (DW_TAG_subprogram)
<491> DW_AT_external : 1
<491> DW_AT_name : (indirect string, offset: 0x2b): printLocal
<495> DW_AT_decl_file : 1
<496> DW_AT_decl_line : 42
<497> DW_AT_decl_column : 6
<498> DW_AT_low_pc : 0x12ff
<4a0> DW_AT_high_pc : 0x129
<4a8> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
<4aa> DW_AT_GNU_all_tail_call_sites: 1
<4aa> DW_AT_sibling : <0x527>
<2><4ae>: Abbrev Number: 20 (DW_TAG_variable)
<4af> DW_AT_name : (indirect string, offset: 0x13d): c1_loc
<4b3> DW_AT_decl_file : 1
<4b4> DW_AT_decl_line : 43
<4b5> DW_AT_decl_column : 10
<4b6> DW_AT_type : <0x91>
<4ba> DW_AT_location : 2 byte block: 91 52 (DW_OP_fbreg: -46)
<2><4bd>: Abbrev Number: 20 (DW_TAG_variable)
<4be> DW_AT_name : (indirect string, offset: 0xc): i_loc
<4c2> DW_AT_decl_file : 1
<4c3> DW_AT_decl_line : 44
<4c4> DW_AT_decl_column : 9
<4c5> DW_AT_type : <0x65>
<4c9> DW_AT_location : 2 byte block: 91 58 (DW_OP_fbreg: -40)
<2><4cc>: Abbrev Number: 20 (DW_TAG_variable)
<4cd> DW_AT_name : (indirect string, offset: 0x126): c2_loc
<4d1> DW_AT_decl_file : 1
<4d2> DW_AT_decl_line : 45
<4d3> DW_AT_decl_column : 10
<4d4> DW_AT_type : <0x91>
<4d8> DW_AT_location : 2 byte block: 91 53 (DW_OP_fbreg: -45)
<2><4db>: Abbrev Number: 20 (DW_TAG_variable)
<4dc> DW_AT_name : (indirect string, offset: 0xce): d_loc
<4e0> DW_AT_decl_file : 1
<4e1> DW_AT_decl_line : 46
<4e2> DW_AT_decl_column : 12
<4e3> DW_AT_type : <0x334>
<4e7> DW_AT_location : 2 byte block: 91 60 (DW_OP_fbreg: -32)
<2><4ea>: Abbrev Number: 20 (DW_TAG_variable)
<4eb> DW_AT_name : (indirect string, offset: 0x333): c3_loc
<4ef> DW_AT_decl_file : 1
<4f0> DW_AT_decl_line : 47
<4f1> DW_AT_decl_column : 10
<4f2> DW_AT_type : <0x91>
<4f6> DW_AT_location : 2 byte block: 91 54 (DW_OP_fbreg: -44)
<2><4f9>: Abbrev Number: 20 (DW_TAG_variable)
<4fa> DW_AT_name : (indirect string, offset: 0x32d): f_loc
<4fe> DW_AT_decl_file : 1
<4ff> DW_AT_decl_line : 48
<500> DW_AT_decl_column : 11
<501> DW_AT_type : <0x364>
<505> DW_AT_location : 2 byte block: 91 5c (DW_OP_fbreg: -36)
<2><508>: Abbrev Number: 20 (DW_TAG_variable)
<509> DW_AT_name : (indirect string, offset: 0x159): c4_loc
<50d> DW_AT_decl_file : 1
<50e> DW_AT_decl_line : 49
<50f> DW_AT_decl_column : 10
<510> DW_AT_type : <0x91>
<514> DW_AT_location : 2 byte block: 91 55 (DW_OP_fbreg: -43)
<2><517>: Abbrev Number: 20 (DW_TAG_variable)
<518> DW_AT_name : (indirect string, offset: 0x1e): s_loc
<51c> DW_AT_decl_file : 1
<51d> DW_AT_decl_line : 50
<51e> DW_AT_decl_column : 11
<51f> DW_AT_type : <0x5e>
<523> DW_AT_location : 2 byte block: 91 56 (DW_OP_fbreg: -42)
when I use GDB to debug the program, I get:
(gdb) info locals
c1_loc = 97 'a'
i_loc = 1
c2_loc = 98 'b'
d_loc = 2
c3_loc = 99 'c'
f_loc = 3
c4_loc = 100 'd'
s_loc = 4
I don't know how GDB get the name of the local variables, hope someone could help me.

Related

Cannot connect to mqtt by using esp32

WiFi connected
IP address:
192.168.1.xxx
Attempting MQTT connection...connected
Guru Meditation Error: Core 1 panic'ed (IllegalInstruction). Exception was unhandled.
Memory dump at 0x400d25bc: ee650213 00f01d0a 41004136
Core 1 register dump:
PC : 0x400d25c1 PS : 0x00060930 A0 : 0x00000000 A1 : 0x3ffb4010
A2 : 0x75e82caf A3 : 0x75e82caf A4 : 0x3ffc2f84 A5 : 0x00000000
A6 : 0x00000000 A7 : 0x00000000 A8 : 0x800d24dc A9 : 0x3ffb3ff0
A10 : 0x00000001 A11 : 0x00000001 A12 : 0x00000010 A13 : 0x3ffc2f84
A14 : 0x3ffb927c A15 : 0x80000001 SAR : 0x0000000a EXCCAUSE: 0x00000000
EXCVADDR: 0x00000000 LBEG : 0x40084415 LEND : 0x4008441d LCOUNT : 0x00000026
Backtrace:0x400d25be:0x3ffb4010
ELF file SHA256: 0000000000000000
Rebooting...
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13864
load:0x40080400,len:3608
entry 0x400805f0
Connecting to xxx
Guys, i got bugged when connecting to mqtt server. I'm using ESP32.
Here is my code for connecting.
void connectMQTT(void *pvParameters) {
vTaskDelay(6000 / portTICK_PERIOD_MS);
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = "FreeRTOS";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("connected");
client.subscribe("denled");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 2 seconds");
delay(2000 / portTICK_PERIOD_MS);
}
}
}
Here is my task. The default running core on my arduino ide is 1
xTaskCreatePinnedToCore(
connectMQTT
, "MQTTConnection" // Task name
, 2048 // Stack size (bytes)
, NULL
, 3 // Priority
, NULL
, ARDUINO_RUNNING_CORE);
Thanks for reading. This is the first time i post, so if there any feedback is always good for me

gdb doesn't find debug info for local static variables

I'm having trouble accessing debug information for local static variables with gdb. I created a very simple example that shows the behaviour:
int global = 0;
static int g_static = 1;
int main(void)
{
static int l_static = 2;
return global + g_static + l_static;
}
I compiled with arm-none-eabi-gcc (I'm compiling for an MCU target) using -O0 and -gdwarf-2 and I can see the debug information for all 3 variables in the output of objdump -g:
<1><29>: Abbrev Number: 2 (DW_TAG_variable)
<2a> DW_AT_name : (indirect string, offset: 0x9): global
<2e> DW_AT_decl_file : 1
<2f> DW_AT_decl_line : 1
<30> DW_AT_decl_column : 5
<31> DW_AT_type : <0x3c>
<35> DW_AT_external : 1
<36> DW_AT_location : 5 byte block: 3 0 0 0 0 (DW_OP_addr: 0)
<1><3c>: Abbrev Number: 3 (DW_TAG_base_type)
<3d> DW_AT_byte_size : 4
<3e> DW_AT_encoding : 5 (signed)
<3f> DW_AT_name : int
<1><43>: Abbrev Number: 4 (DW_TAG_variable)
<44> DW_AT_name : (indirect string, offset: 0xac): g_static
<48> DW_AT_decl_file : 1
<49> DW_AT_decl_line : 2
<4a> DW_AT_decl_column : 12
<4b> DW_AT_type : <0x3c>
<4f> DW_AT_location : 5 byte block: 3 0 0 0 0 (DW_OP_addr: 0)
<1><55>: Abbrev Number: 5 (DW_TAG_subprogram)
<56> DW_AT_external : 1
<57> DW_AT_name : (indirect string, offset: 0x17): main
<5b> DW_AT_decl_file : 1
<5c> DW_AT_decl_line : 4
<5d> DW_AT_decl_column : 5
<5e> DW_AT_prototyped : 1
<5f> DW_AT_type : <0x3c>
<63> DW_AT_low_pc : 0x0
<67> DW_AT_high_pc : 0x28
<6b> DW_AT_frame_base : 0x0 (location list)
<6f> DW_AT_GNU_all_call_sites: 1
<2><70>: Abbrev Number: 4 (DW_TAG_variable)
<71> DW_AT_name : (indirect string, offset: 0x0): l_static
<75> DW_AT_decl_file : 1
<76> DW_AT_decl_line : 6
<77> DW_AT_decl_column : 14
<78> DW_AT_type : <0x3c>
<7c> DW_AT_location : 5 byte block: 3 0 0 0 0 (DW_OP_addr: 0)
In the symbol table l_static is given a suffix to make it unique and prevent ambiguity. nm output:
00000000 b $d
00000000 d $d
00000000 d $d
0000001c t $d
00000000 t $t
00000000 d g_static
00000000 B global
00000000 d l_static.0
00000001 T main
Yet when I try to access it using gdb, I can only access debug info for global and g_static but not for l_static or even 'l_static.0'. It looks like gdb knows about the existence of l_static.0but can't find the related debug info.:
(gdb) ptype global
type = int
(gdb) ptype g_static
type = int
(gdb) ptype l_static
No symbol "l_static" in current context.
(gdb) ptype 'l_static.0'
type = <data variable, no debug info>
I have tried with gdb 7.6.1 and 11.2 with the same result. As far as I understand it the information is there, as shown by the output of objdump -g. But for some reason gdb can't find it.
My gut feeling is that this might be related to the way gcc appends the .0 to the local static's symbol name. Maybe this leads to a mismatch between the symbol name and the name related to the debug info?
Hoping for anyone who can shed some light on this. Thanks in advance!
You need to stop inside the main function to see that variable:
I found out how to do it without running the binary and setting a breakpoint.
(gdb) ptype main::l_static
type = int
Apparently gdb knows in which function the local static is defined and lets you access it in this c++ namespace-style way, even if the relevant stack frame has not been selected. This is documented in section 10.3 of the gdb manual.

How to get the value of a variable in dwarf?

I am parsing dwarf files, and I want to get the value of a variable or a pointer.
For example,
#include<stdio.h>
int main(){
int *a=malloc(4*sizeof(int));
a[0]=1;
int *b=&a;
int c=a[0];
return 0;
}
I got the dwarf debug information like this:
<2><304>: Abbrev Number: 17 (DW_TAG_variable)
<305> DW_AT_name : a
<307> DW_AT_decl_file : 1
<308> DW_AT_decl_line : 4
<309> DW_AT_decl_column : 10
<30a> DW_AT_type : <0x341>
<30e> DW_AT_location : 2 byte block: 91 58 (DW_OP_fbreg: -40)
<2><311>: Abbrev Number: 18 (DW_TAG_subprogram)
<312> DW_AT_external : 1
<312> DW_AT_name : (indirect string, offset: 0x3f): malloc
<316> DW_AT_decl_file : 8
<317> DW_AT_decl_line : 0
<318> DW_AT_prototyped : 1
<318> DW_AT_type : <0x47>
<31c> DW_AT_declaration : 1
<31c> DW_AT_sibling : <0x326>
<3><320>: Abbrev Number: 19 (DW_TAG_formal_parameter)
<321> DW_AT_type : <0x39>
<3><325>: Abbrev Number: 0
<2><326>: Abbrev Number: 17 (DW_TAG_variable)
<327> DW_AT_name : b
<329> DW_AT_decl_file : 1
<32a> DW_AT_decl_line : 7
<32b> DW_AT_decl_column : 10
<32c> DW_AT_type : <0x341>
<330> DW_AT_location : 2 byte block: 91 60 (DW_OP_fbreg: -32) [without DW_AT_frame_base]
<2><333>: Abbrev Number: 17 (DW_TAG_variable)
<334> DW_AT_name : c
<336> DW_AT_decl_file : 1
<337> DW_AT_decl_line : 8
<338> DW_AT_decl_column : 9
<339> DW_AT_type : <0x65>
<33d> DW_AT_location : 2 byte block: 91 54 (DW_OP_fbreg: -44) [without DW_AT_frame_base]
I get the name,type,frame base offset of a,b and c, but could I know the value of int *b and int c ?

Input integers from CSV file( graph adjacency list) in C

I'm trying to implement the BFS algorithm to determine the shortest path between two nodes.For that I have been given the graph as an input csv file which is the adjacency list.I plan to store this list as an array of struct "rel" and get input from the file shown in the code.However, the output doesn't show the correct values.
#include<stdlib.h>
#include<stdio.h>
typedef struct relation // to store the pair of integers in a csv file line (c connected to y
{
int x;
int y;
}rel; // relation
void split(char* buffer,char* string1,char* string2) // spilts buffer into two strings seperated by ,
{
char* buffer_trav = buffer; // trav ptr in buffer
char* string_trav = string1; // trav ptr to string 1 or 2(after ',' is read)
while(*buffer_trav!='\0')
{
if(*buffer_trav==',')
{
string_trav = string2;
buffer_trav+=1;
}
else
{
*string_trav = *buffer_trav;
string_trav+=1;
buffer_trav+=1;
}
}
}
int main(void)
{
FILE* fp = fopen("graph.csv","r"); // reading csv file
int max_number_data = 100; // maximum number of edge relations in the file
rel graph[max_number_data];
for(int i=0;i<max_number_data;i++)
{
graph[i].x=1 ;
graph[i].y=-1 ; // setting initial value to be used as a check point for other functions
}
char buffer[10];//buffer for input
char x_buffer[5];// buffer for name
char y_buffer[5]; // buffer for password
int count=0;
while(fgets(buffer,10,fp)!=NULL)
{
char* ptr; // to be used to convert string to integer;
split(buffer,x_buffer,y_buffer); // splits into two strings
printf("%s : %s;\n",x_buffer,y_buffer); // To debug
graph[count].x = (int)strtol(x_buffer,&ptr,10); // converts string to longint which is later cat into int
graph[count].y = (int)strtol(y_buffer,&ptr,10); // " " " " " " " " " " " " "" " " " " "" " "" "" " " ""
count++;
}
fclose(fp);
}
Input file:
0,1
0,2
0,3
0,4
0,5
0,6
0,7
0,8
0,10
0,11
0,12
0,13
0,17
0,19
0,21
0,31
1,0
1,2
1,3
1,7
1,13
1,17
1,19
1,21
1,30
2,0
2,1
2,3
2,7
2,8
2,9
2,13
2,27
2,28
2,32
3,0
3,1
3,2
3,7
3,12
3,13
4,0
4,6
4,10
5,0
5,6
5,10
5,16
6,0
6,4
6,5
6,16
7,0
7,1
7,2
7,3
8,0
8,2
8,30
8,32
8,33
9,2
9,33
10,0
10,4
10,5
11,0
12,0
12,3
13,0
13,1
13,2
13,3
13,33
14,32
14,33
15,32
15,33
16,5
16,6
17,0
17,1
18,32
18,33
19,0
19,1
19,33
20,32
20,33
21,0
21,1
22,32
22,33
23,25
23,27
23,29
23,32
23,33
24,25
24,27
24,31
25,23
25,24
25,31
26,29
26,33
27,2
27,23
27,24
27,33
28,2
28,31
28,33
29,23
29,26
29,32
29,33
30,1
30,8
30,32
30,33
31,0
31,24
31,25
31,28
31,32
31,33
32,2
32,8
32,14
32,15
32,18
32,20
32,22
32,23
32,29
32,30
32,31
32,33
33,8
33,9
33,13
33,14
33,15
33,18
33,19
33,20
33,22
33,23
33,26
33,27
33,28
33,29
33,30
33,31
33,32
The output( Debugging ) I get is:
0`#?d : 1
;
0`#?d : 2
;
0`#?d : 3
;
0`#?d : 4
;
0`#?d : 5
;
0`#?d : 6
;
0`#?d : 7
;
0`#?d : 8
;
0`#?d : 10
;
0`#?d : 11
;
0`#?d : 12
;
0`#?d : 13
;
0`#?d : 17
;
0`#?d : 19
;
0`#?d : 21
;
0`#?d : 31
;
1`#?d : 0
;
1`#?d : 2
;
1`#?d : 3
;
1`#?d : 7
;
1`#?d : 13
;
1`#?d : 17
;
1`#?d : 19
;
1`#?d : 21
;
1`#?d : 30
;
2`#?d : 0
;
2`#?d : 1
;
2`#?d : 3
;
2`#?d : 7
;
2`#?d : 8
;
2`#?d : 9
;
2`#?d : 13
;
2`#?d : 27
;
2`#?d : 28
;
2`#?d : 32
;
3`#?d : 0
;
3`#?d : 1
;
3`#?d : 2
;
3`#?d : 7
;
3`#?d : 12
;
3`#?d : 13
;
4`#?d : 0
;
4`#?d : 6
;
4`#?d : 10
;
5`#?d : 0
;
5`#?d : 6
;
5`#?d : 10
;
5`#?d : 16
;
6`#?d : 0
;
6`#?d : 4
;
6`#?d : 5
;
6`#?d : 16
;
7`#?d : 0
;
7`#?d : 1
;
7`#?d : 2
;
7`#?d : 3
;
8`#?d : 0
;
8`#?d : 2
;
8`#?d : 30
;
8`#?d : 32
;
8`#?d : 33
;
9`#?d : 2
;
9`#?d : 33
;
10#?d : 0
;
10#?d : 4
;
10#?d : 5
;
11#?d : 0
;
12#?d : 0
;
12#?d : 3
;
13#?d : 0
;
13#?d : 1
;
13#?d : 2
;
13#?d : 3
;
13#?d : 33
;
14#?d : 32
;
14#?d : 33
;
15#?d : 32
;
15#?d : 33
;
16#?d : 5
;
16#?d : 6
;
17#?d : 0
;
17#?d : 1
;
18#?d : 32
;
18#?d : 33
;
19#?d : 0
;
19#?d : 1
;
19#?d : 33
;
20#?d : 32
;
20#?d : 33
;
21#?d : 0
;
21#?d : 1
;
22#?d : 32
;
22#?d : 33
;
23#?d : 25
;
23#?d : 27
;
23#?d : 29
;
23#?d : 32
;
23#?d : 33
;
24#?d : 25
;
24#?d : 27
;
24#?d : 31
;
25#?d : 23
;
25#?d : 24
;
zsh: segmentation fault ./a.out
The issue was that strings were not terminated with null characters.Also, the segmentation fault occurred because while the csv file had around 200 lines, I initiated maximum input lines to 100.

Trouble implementing crib drag

so I'm enrolled in Stanford's Cryptography class on Coursera and I've been struggling with the first programming assignment (I'm a few weeks behind.)
I've been playing around with different variations of this code for a few weeks to try and remove the issues mentioned below...
At first, I thought I was getting a successful crib-drag, but then I realized a multitude of issues, none of which I've been able to solve:
The "deciphered" results were shortening from the wrong end of the word as the crib is dragged across the XOR of the two cipher texts ("The" > "Th" > "T" instead of "The" > "he" > "e")
The result of crib dragging isn't the text of the other message, but the crib itself...in other words, no matter what crib I choose, the first X number of indices ALWAYS return the crib itself
Here's the code:
def string_xor(a, b):
return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a ,b)])
def manual_crib_drag(word):
with open("two_ciphers.txt", "r") as f:
cipher1 = f.readline()
cipher2 = f.readline()
xor = string_xor(cipher1, cipher2)
word_hex = word.encode("hex")
for x in range(len(xor)):
try:
result = string_xor(xor[x:x+len(word_hex)], word_hex)\
.strip().decode("hex")
print x, ":", result
except TypeError, e: print
Here are the results when running manual_crib_drag("The "):
0 : The
1 : The
2 : The
3 : The
4 : The
5 : The
6 : The
7 : The
8 : The
9 : The
10 : The
11 : The
12 : The
13 : The
14 : The
15 : The
16 : The
17 : The
18 : The
19 : The
20 : The
21 : The
22 : The
23 : The
24 : The
25 : The
26 : The
27 : The
28 : The
29 : The
30 : The
31 : The
32 : The
33 : The
34 : The
35 : The
36 : The
37 : The
38 : The
39 : The
40 : The
41 : The
43 : The?
46 : Tcn$
53 : ??S
71 : PN?
80 : CT"#
83 : ?Q?
88 : `n$
94 : P'e<
99 : U??
118 : b}l
123 : Ǹd?
132 : Tokf
138 : X6%
148 : YW0-
155 : ??4d
161 : ???
171 : ??!
173 : ??d1
177 : Uy?G
200 : hm
202 : de*t
218 : Xn q
238 : Ti0:
249 : 4|5!
253 : i?u
258 : ;G+
263 : t?Qq
269 : )?
275 : t??
282 : Z
285 : G?d
313 : sLtU
319 : !9u?
320 : yo
325 : ?kv0
329 : Gx??
331 : Dﺹ?
For completeness, here are the two cipher texts used in the example:
32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd2061bbde24eb76a19d84aba34d8de287be84d07e7e9a30ee714979c7e1123a8bd9822a33ecaf512472e8e8f8db3f9635c1949e640c621854eba0d79eccf52ff111284b4cc61d11902aebc66f2b2e436434eacc0aba938220b084800c2ca4e693522643573b2c4ce35050b0cf774201f0fe52ac9f26d71b6cf61a711cc229f77ace7aa88a2f19983122b11be87a59c355d25f8e4
32510bfbacfbb9befd54415da243e1695ecabd58c519cd4bd90f1fa6ea5ba47b01c909ba7696cf606ef40c04afe1ac0aa8148dd066592ded9f8774b529c7ea125d298e8883f5e9305f4b44f915cb2bd05af51373fd9b4af511039fa2d96f83414aaaf261bda2e97b170fb5cce2a53e675c154c0d9681596934777e2275b381ce2e40582afe67650b13e72287ff2270abcf73bb028932836fbdecfecee0a3b894473c1bbeb6b4913a536ce4f9b13f1efff71ea313c8661dd9a4ce
And the result of XORing these two cipher texts is:
PRX]
TS\TW]SW\[\VTS\^W[
TVSPZWSQV
[TZ[P\Q[PZRUS[TVTU[ZUQT[][SZRTWV
h
I'm not sure why it's broken into separate lines, but my guess is that it has to do with spaces in the cipher text XOR result...encasing the return of the string_xor function inside of another join, seems to do the trick though, but because it doesn't seem to affect the results of the crib drag, I left it out of the provided code:
" ".join("".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a ,b)]).split())
I'd appreciate any help! Thanks in advance.
try converting it first to ascii and then do the xor
x = strxor(unhexlify(ciphertexts[0]),unhexlify(target))
print "Ciphertext[0] xor Target\n"
crib = raw_input("Enter Crib:>")
print "Crib\n-->%s<--"%crib
# Crib Drag
for i in range(len(x)):
z = x[i:]
print "\n[%d]"%i
print "%s"%strxor(z,crib)

Resources